具有参数的Kotlin线程安全本机懒惰单例 [英] Kotlin thread safe native lazy singleton with parameter

查看:430
本文介绍了具有参数的Kotlin线程安全本机懒惰单例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,我们可以使用Double Checked Locking&易失性:

In java we can write thead-safe singletons using double Checked Locking & volatile:

    public class Singleton {
        private static volatile Singleton instance;

        public static Singleton getInstance(String arg) {
        Singleton localInstance = instance;
        if (localInstance == null) {
            synchronized (Singleton.class) {
                localInstance = instance;
                if (localInstance == null) {
                    instance = localInstance = new Singleton(arg);
                }
            }
        }
        return localInstance;
    }
}

我们如何用Kotlin编写它?

How we can write it in kotlin?

object A {
    object B {}
    object C {}
    init {
        C.hashCode()
    }
}

我用Kotlin反编译器得到了

I used kotlin decompiler to get that

public final class A {
   public static final A INSTANCE;

   private A() {
      INSTANCE = (A)this;
      A.C.INSTANCE.hashCode();
   }
   static {
      new A();
   }

   public static final class B {
      public static final A.B INSTANCE;
      private B() {
         INSTANCE = (A.B)this;
      }
      static {
         new A.B();
      }
   }

   public static final class C {
      public static final A.C INSTANCE;
      private C() {
         INSTANCE = (A.C)this;
      }
      static {
         new A.C();
      }
   }
}

所有对象都有static块中的构造函数调用.基于此,我们可以认为它不是惰性的.

All of object have constructor invoke in static block. Based on it, we can think that it's not lazy.

    class Singleton {
        companion object {
            val instance: Singleton by lazy(LazyThreadSafetyMode.PUBLICATION) { Singleton() }
        }
    }

反编译:

public static final class Companion {
      // $FF: synthetic field
      private static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.property1(new PropertyReference1Impl(Reflection.getOrCreateKotlinClass(Singleton.Companion.class), "instance", "getInstance()Lru/example/project/tech/Singleton;"))};

      @NotNull
      public final Singleton getInstance() {
         Lazy var1 = Singleton.instance$delegate;
         KProperty var3 = $$delegatedProperties[0];
         return (Singleton)var1.getValue();
      }

      private Companion() {
      }

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

我希望Kotlin开发人员将来可以进行非反射式实现...

I hope Kotlin developers will make non reflection implementation in future...

推荐答案

Kotlin与您的Java代码等效,但是更加安全.甚至对于Java而言,也不建议您双锁检查.在Java中,您应该在静态上使用内部类,该类也在

Kotlin has an equivalent of your Java code, but more safe. Your double lock check is not recommended even for Java. In Java you should use an inner class on the static which is also explained in Initialization-on-demand holder idiom.

但是那是Java. 在Kotlin中,只需使用一个对象(还有一个懒惰的委托):

But that's Java. In Kotlin, simply use an object (and optionally a lazy delegate):

object Singletons {
    val something: OfMyType by lazy() { ... }

    val somethingLazyButLessSo: OtherType = OtherType()
    val moreLazies: FancyType by lazy() { ... }
}

然后您可以访问任何成员变量:

You can then access any member variable:

// Singletons is lazy instantiated now, then something is lazy instantiated after.  
val thing = Singletons.something // This is Doubly Lazy!

// this one is already loaded due to previous line
val eager = Singletons.somethingLazyButLessSo

// and Singletons.moreLazies isn't loaded yet until first access...

Kotlin故意避免了人们对Java单身人士的困惑.并避免这种模式的错误版本"-其中有很多.相反,它提供了更简单,最安全的单例形式.

Kotlin intentionally avoids the confusion people have with singletons in Java. And avoids the "wrong versions" of this pattern -- of which there are many. It instead provides the simpler and the safest form of singletons.

考虑到使用lazy(),如果您有其他成员,则每个成员都各自为懒.并且由于它们是在传递给lazy()的lambda中初始化的,因此您可以做有关自定义构造函数和每个成员属性的事情.

Given the use of lazy(), if you have other members each would individually be lazy. And since they are initialized in the lambda passed to lazy() you can do things that you were asking about for about customizing the constructor, and for each member property.

因此,您有Singletons对象的延迟加载(在实例的首次访问时为 ),然后是something的延迟加载(在成员的首次访问时为 >),并在对象构造方面具有完全的灵活性.

As a result you have lazy loading of Singletons object (on first access of instance), and then lazier loading of something (on first access of member), and complete flexibility in object construction.

另请参见:

  • lazy() function
  • Lazy thread safe mode options
  • Object declarations

作为补充,查看Kotlin的对象注册表类型库,它们类似于依赖项注入,为您提供具有注入选项的单例:

As a side note, look at object registry type libraries for Kotlin that are similar to dependency injection, giving you singletons with injection options:

  • Injekt - I'm the author
  • Kodein - Very similar and good

这篇关于具有参数的Kotlin线程安全本机懒惰单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆