4

我正在尝试将我的项目的某些部分javakotlin. 其中之一是单例管理器类。java类看起来像这样

public class Manager {
  private static volatile Manager Instance = null;
  private static final Object InstanceLock = new Object();
  private Manager(Object1 object1, Object2 object2, Object3 object3){//...};
  public static boolean isInitialized(){
    synchronized(InstanceLock){
        return Instance == null;
    }
  }
  public static void initialize(Object1 object1, Object2 object2, Object3 object3){
      if(Instance == null){
         synchronized(InstanceLock){
             if(Instance == null){Instance = new Manager(object1, object2, object3};
         }
      }
  }
  public static getInstance(){
       Precondition.checkNotNull(Instance, msg...);
       return Instance;
  }
}

另外,我将.kt 反编译回java。在伴随类中,我得到以下代码。

public static final class Companion {
  @Nullable
  public final Manager getInstance() {
     return Manager.instance;
  }

  private final void setInstance(Manager var1) {
     Manager.instance = var1;
  }

  private final Object getInstanceLock() {
     return Manager.InstanceLock;
  }

  public final boolean isInitialized() {
     Object var1 = Manager.Companion.getInstanceLock();
     synchronized(var1){}

     boolean var4;
     try {
        var4 = Manager.Companion.getInstance() == null;
     } finally {
        ;
     }

     return var4;
  }

  public final void initialize(@NotNull String string1, @NotNull String string2) {
     Intrinsics.checkParameterIsNotNull(string1, "string1");
     Intrinsics.checkParameterIsNotNull(string2, "string2");
     if (((Manager.Companion)this).getInstance() == null) {
        Object var3 = ((Manager.Companion)this).getInstanceLock();
        synchronized(var3){}

        try {
           if (Manager.Companion.getInstance() == null) {
              Manager.Companion.setInstance(new Manager(string1, string2, (DefaultConstructorMarker)null));
           }

           Unit var5 = Unit.INSTANCE;
        } finally {
           ;
        }
     }

  }

  private Companion() {
  }

  // $FF: synthetic method
  public Companion(DefaultConstructorMarker $constructor_marker) {
     this();
  }

}

1) 如何通过在 kotlin 伴随对象中使用 lateinit 或lazy 来实现线程安全、单例?如我所见,反编译的 java 代码在初始化函数中有一个同步调用,但在同步主体中没有任何内容。

2)我认为 kotlin object/lazy 带有线程安全保证,我如何在双重检查锁定模式中利用它?

3)有比双重检查锁定模式更好的模式吗?假设构造函数确实需要参数。

4)由于我试图使将此管理器类转换为 kotlin 文件的影响尽可能小(此管理器​​文件应该与其余的 java 代码一起使用),最好的方法是什么?我确实注意到我必须在伴随对象内添加@Jvmstatic或添加@Jvmfield一些其他变量或函数,这样我就不必更新在管理器中调用这些静态字段的其他 java 文件。

5)另外的问题,如果这个管理器现在在纯 kotlin 环境中工作,实现具有多个参数的单例类的最佳实践是什么?

4

2 回答 2

1

第一个答案没有解决同步问题,顺便说一句,这仍然是一个被低估的复杂性。仍然有很多人跑来跑去说只是做双重检查锁定。但是有一些非常有说服力的论点表明 DCL 并不总是有效。

不过,有趣的是,我最近遇到了同样的问题并找到了这篇文章。虽然我第一次发现它时不喜欢它,但我重温了几次并对其进行了热身,很大程度上是因为:

  • 作者从 Kotlin 标准库中获取了代码
  • 结果是一个参数化的机制,虽然有点难看,但可以重用,这非常引人注目

请注意,主要问题都在此处理中提出:

  • 同步
  • 复杂的初始化
  • 参数化初始化(在 Android 中至关重要,其中 Context God 对象不可根除)
  • 生成的编译代码

简而言之,我认为这几乎是关于这个主题的第一个也是最后一个词,令人惊讶的是,在 Medium 上找到了。

于 2017-11-11T18:09:27.007 回答
0

我无法回答您的所有问题,但有一种在 Kotlin 中创建单例类的明确方法。

代替class类名前面的前缀,使用object.

例如,

object Manager {
    // your implementation
}

这使此类成为单例,您可以直接从 Java 中使用它Manager.getInstance()(我不记得确切的语法,但这应该可以)。Kotlin 为您创建它。

您可以查看内容以获取更多参考。

希望对您有所帮助。

于 2017-11-11T18:02:55.553 回答