3

在使用静态初始化实现线程安全的单例时,Initialize-On-Demand 习语真的有必要吗,还是一个简单的实例静态声明就足够了?

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

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

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

对比

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/

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

4

3 回答 3

3

那么我可以说这些文章是 7-9 岁。

现在我们拥有 > Java 1.5,我们拥有枚举的能力enum。根据 'Josh Block' 写单例的最好方法是写一个单元素枚举

public enum MySingleton{
    Singleton;

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

但是对于您的问题,我想使用这两种实现都没有问题。我个人更喜欢第一个选项,因为它简单易懂。

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

还要使类成为最终类,因为我们可以通过扩展类来违反单例。

于 2011-07-25T06:38:47.807 回答
3

在第一种方法中,一旦您加载Singleton类,您的单例就会被创建。getInstance()另一方面,一旦您调用方法,它将被创建。Singleton在调用之前,类可能有很多原因要加载getInstance。因此,当您实际使用它时,您很可能会更早地初始化它,这违背了延迟初始化的目的。是否需要延迟初始化是另一回事。

于 2011-07-25T06:42:00.203 回答
2

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

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

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

-dg

于 2011-07-25T06:57:11.540 回答