Singleton实现中的Initialize-On-Demand习语与简单的静态初始化程序

时间:2011-07-25 06:22:17

标签: java concurrency singleton lazy-initialization static-initialization

使用静态初始化实现线程安全单例时,Initialize-On-Demand习惯用法是否真的必要,或者实例的简单静态声明是否足够?

将实例简单声明为静态字段:

class Singleton
{
 private static Singleton instance=new Singleton();

 private Singleton () {..}
 public static Singleton getInstance()
 {
  return instance;
 }
}

VS

class Singleton {
   static class SingletonHolder {
      static final Singleton INSTANCE = new Singleton();
   }

   private Singleton () {..}

   public static Singleton getInstance() {
      return SingletonHolder.INSTANCE;
   }
}

我问这个是因为Brian Goetz在本文中推荐了第一种方法:

http://www.ibm.com/developerworks/java/library/j-dcl/index.html

虽然他在本文中提出了后者

http://www.ibm.com/developerworks/library/j-jtp03304/

后一种方法是否提供了前者没有的任何好处?

3 个答案:

答案 0 :(得分:3)

我能说什么这些文章是7-9岁。

现在我们有> Java 1.5我们有枚举的力量enum。根据'Josh Block'编写单例的最佳方法是编写单元素枚举

public enum MySingleton{
    Singleton;

    // rest of the implementation.
    // ....
}

但是对于你的问题,我猜使用其中任何一个实现都没有问题。我个人更喜欢第一种选择,因为它简单明了,易于理解。

但要注意循环漏洞,我们可以通过序列化和反序列化对象或通过复制对象来同时在同一个JVM中创建这些类的更多对象。

同样让课程成为最终,因为我们可以通过扩展课程来违反单身。

答案 1 :(得分:3)

在第一种方法中,一旦加载Singleton类,就会创建单例。另一方面,一旦调用getInstance()方法,它就会被创建。在致电Singleton之前,getInstance类可能有很多理由要加载。因此,当您实际使用它时,您很可能会更早地将其初始化,这会使延迟初始化失败。是否需要延迟初始化是一个单独的故事。

答案 2 :(得分:2)

简单声明模式在加载类Singleton时构造单例。当调用Singeton.getInstance()时,初始化按需习惯用法构造单例 - 即,当加载类SingetonHolder时。

所以这些都是相同的,除了时间;第二个选项允许您延迟初始化。什么时候选择其中一个取决于(除其他事项外)你在Singleton的构造函数中做了多少工作。如果它很多,您可以通过按需初始化看到改进的应用程序启动时间。

那就是说,我的建议是尽量不要做太多,以便最简单的模式适合你。

-dg