迟到,懒惰和单身模式在kotlin

我试图将我的项目的一部分从java转换到kotlin 。 其中之一是单身经理班。 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 companion对象中的lateinit或lazy来实现线程安全,单例? 正如我所看到的,反编译的java代码在初始化函数中有一个同步调用,但在同步主体中没有任何内容。

2)我认为kotlin对象/懒惰带有线程安全保证,我怎么利用它在双重检查的锁定模式?

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

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

5)另外的问题,如果这个经理现在在纯kotlin环境中工作,那么实现一个带有多个参数的单例类的最佳做法是什么?

我没有回答你所有的问题,但是在Kotlin中有一个定义的方法来创建单例类。

使用object而不是类名前面的class前缀。

例如,

 object Manager { // your implementation } 

这使得这个类单例,你可以直接使用这个从Java像Manager.getInstance() (我没有记住确切的语法,但这应该工作)。 Kotlin为你创造它。

你可以检查这个更多的参考。

希望它能帮助你一点。

第一个答案没有解决同步问题,顺便说一下,这个问题仍然是一个复杂的问题。 还有很多人跑来跑去说简单地做双重锁定。 但是有一些非常引人注目的观点表明,DCL并不总是有效的。

有趣的是,我最近也遇到了同样的问题,发现[this article][1] 。 虽然我第一次发现它时不喜欢这个,但是我反抗了几次并加热了它,主要是因为:

  • 作者去了Kotlin stdlib的代码
  • 结果是一个参数化的机制,虽然丑陋提供重用,这是非常有说服力的

请注意,所有这些主要问题都在这个处理中提出:

  • 同步
  • 复杂的初始化
  • 参数化初始化(在Android中非常重要,上下文对象是无法根除的)
  • 产生编译的代码

简而言之,我认为这是这个话题上的第一个也是最后一个字,在Medium上很惊人。