单身模式(Bill Pugh的解决方案)

时间:2011-05-24 11:46:53

标签: java design-patterns singleton

我正在阅读关于单身人士模式的维基,我不确定我是否理解这一点:https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom部分内容是正确的。

为了简单起见:为什么Bill Pugh的解决方案比上面的例子更好?

是因为VM在实际使用之前没有加载静态类或类似的东西,所以在转向getInstance()方法之前我们不创建对象? 那个方法线程安全只是在初始化对象的程度吗?

5 个答案:

答案 0 :(得分:29)

我认为Pugh先生的版本受到高度重视,因为它仅在调用getInstance()时执行单例的实例化,即不在加载类(包含getInstance方法的类)时执行。如果你的单身人士建筑做了昂贵的,那么这对你来说可能是一个优势。如果你像世界上大多数人一样,他们的单身人士只是为了避免使用静态方法(并且你没有转向依赖注入框架),那么我就不会失去任何睡眠。

正如文章所述,Pugh先生的方法比静态实例变量更懒惰 - 但实际上如果Singleton类被加载,你无论如何都会调用getInstance方法。因此,作为计算机科学的一部分,它很有用,但在现实世界中它的好处值得商榷。

P.S。我不太关心布洛赫先生在这里的例子,因为使用枚举就是说我的单身人士IS-A枚举,这对我来说听起来并不合适(尤其是那些正确地说,从来没有实现过接口的人得到常数)

答案 1 :(得分:20)

JLS保证只在第一次使用它时才加载一个类(使单例初始化变得懒惰),并且类加载是线程安全的(使{{1}方法也是线程安全的)

至于线程安全的原因

因为第一次调用getInstance(),JVM将持有holder类。如果另一个线程同时调用getInstance(),JVM将不会再次加载holder类:它将等待第一个线程完成类加载,并在加载和初始化holder类时,两个线程都会看到holder类正确初始化,因此包含唯一的单例实例。

答案 2 :(得分:7)

  

是因为静态类不是   虚拟机在实际加载之前加载   使用

不仅仅是静态类,任何类。在引用类之前不会加载类。请参阅JLS - 12.4.1 When Initialization Occurs

  

或类似的东西,所以我们没有   在我们转向之前创建对象   getInstance()方法?

完全。

  

也是该方法线程安全   到初始化的程度   对象

发布引用是线程安全的,因此该方法始终是线程安全的,而不仅仅是在创建时

答案 3 :(得分:1)

  

是因为静态类不是   虚拟机在实际加载之前加载   使用或类似的东西,所以我们   我们转之前不要创建对象   到getInstance()方法?

正确。

  

该方法的线程安全性仅在初始化对象的范围内吗?

它确保只创建一个实例,并且除了对完全初始化的实例的引用外,没有客户端接收任何内容。

答案 4 :(得分:1)

解释的关键部分如下:

  

嵌套类引用为no   早些时候(因此加载没有   早于类加载器)比   调用getInstance()的时刻。   因此,该解决方案是线程安全的   不需要特殊语言   构造(即挥发性或   同步)。

Bill Pogh的解决方案提供了懒惰。