【问题标题】:Singleton with or without holder = lazy vs eager initialisation?有或没有持有人的单身人士=懒惰与急切的初始化?
【发布时间】:2016-04-03 01:36:24
【问题描述】:

这是否正确:

  • 使用singleton with a holder 会进行延迟初始化,因为SingletonHolder 类仅在Singleton.getInstance() 运行时才会初始化。这依赖于 SingletonHolder 仅在 Singleton.getInstance() 中被引用。它是线程安全的,因为类加载器负责同步。
  • 使用没有持有者的单例是急切的初始化,因为一旦 Java 遇到引用 Singleton 的代码,它的所有静态字段都会被解析。它也是线程安全的,因为类加载器负责同步。

带支架的单身人士。

public class Singleton {
   private static class SingletonHolder {
      private static final Singleton INSTANCE = new Singleton();
   }
   public static Singleton getInstance() {
      return SingletonHolder.INSTANCE;
   }
   private Singleton(){ }
}

没有支架的单身人士。

public class Singleton{
   private static final Singleton INSTANCE = new Singleton();
   public static Singleton getInstance(){
      return INSTANCE;
   }
   private Singleton(){ }
}

更新以响应@jan 的建议,即这是What is an efficient way to implement a singleton pattern in Java? 的副本。我不同意。我不是在问最好的方法是什么:我只是在问是什么让这两个特定的实现变得懒惰和急切地加载。像xyz's 这样的答案广泛地解决了懒惰与渴望,但不是通过对比我试图检查的两个示例(或者使用相同的关键字,这就是为什么它在我的初始搜索中从未出现过)。

【问题讨论】:

  • 单例有多种实现方式,懒惰/急切取决于你的实现。 stackoverflow.com/a/16580366/705773 可能会有所帮助。
  • 您可以使用静态块验证这一点并打印出一些内容以查看实际字段何时初始化。
  • “使用没有持有者的单例是急切的初始化,因为一旦 Java 遇到引用单例的代码,它的所有静态字段都会被解析。”这是不正确的。例如,如果您通过 import 语句引用此代码,则不会解析静态。

标签: java multithreading singleton eager-loading lazy-initialization


【解决方案1】:

作为对@Sriram 的回应,这是我的测试,以证明急切与延迟加载。

使用支架延迟加载

public class Singleton {
   private static class SingletonHolder {
      static {
         System.out.println("In SingletonHolder static block.");
      }
      private static final Singleton INSTANCE = new Singleton();
   }

   public static Singleton getInstance() {
      System.out.println("In getInstance().");
      return SingletonHolder.INSTANCE;
   }

   private Singleton() {
      System.out.println("In constructor.");
   }

   private void doSomething() {
      System.out.println("Singleton working.");
   }

   public static void main(String[] args) {
      System.out.println("Start of main.");
      Singleton.getInstance().doSomething();
      System.out.println("End of main.");
   }
}

输出显示main方法在getInstance()被调用之前启动,因此被延迟加载。

Start of main.
In getInstance().
In SingletonHolder static block.
In constructor.
Singleton working.
End of main.

无需支架即可快速加载

public class Singleton {

   static {
      System.out.println("In Singleton static block.");
   }

   private static final Singleton INSTANCE = new Singleton();

   public static Singleton getInstance() {
      System.out.println("In getInstance().");
      return INSTANCE;
   }

   private Singleton() {
      System.out.println("In constructor.");
   }

   private void doSomething() {
      System.out.println("Singleton working.");
   }

   public static void main(String[] args) {
      System.out.println("Start of main.");
      Singleton.getInstance().doSomething();
      System.out.println("End of main.");
   }

}

输出显示main 方法在getInstance() 方法被调用之后启动,因此被急切加载。

In Singleton static block.
In constructor.
Start of main.
In getInstance().
Singleton working.
End of main.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 2015-07-16
    • 2022-12-25
    • 1970-01-01
    相关资源
    最近更新 更多