有或没有 holder 的单身人士 = 懒惰与急切的初始化?
Singleton with or without holder = lazy vs eager initialisation?
这是否正确:
- 使用 singleton with a holder 进行延迟初始化,因为 class
SingletonHolder
仅在 Singleton.getInstance()
为 运行 时才初始化。这依赖于 SingletonHolder
仅在 Singleton.getInstance()
中被引用。它是线程安全的,因为 class 加载程序负责同步。
- 使用没有 holder 的单例是急切的初始化,因为一旦 Java 遇到引用
Singleton
的代码,它的所有静态字段都会被解析。它也是线程安全的,因为 class 加载程序负责同步。
有持有人的单身人士。
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(){ }
}
Update 回应@jan 的建议,即这是 What is an efficient way to implement a singleton pattern in Java?. I disagree. I am not asking what is the best way to do it: I am only asking what makes these two specific implementations lazy vs eager loading. Answers like xyz's 的重复,广泛地解决懒惰与急切的问题,但不是通过对比我尝试的两个例子检查(或使用相同的关键字,这就是为什么它从未出现在我的初始搜索中)。
作为对@Sriram 的回应,这是我的测试来证明哪个是急切加载还是延迟加载。
使用 holder 延迟加载
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.
这是否正确:
- 使用 singleton with a holder 进行延迟初始化,因为 class
SingletonHolder
仅在Singleton.getInstance()
为 运行 时才初始化。这依赖于SingletonHolder
仅在Singleton.getInstance()
中被引用。它是线程安全的,因为 class 加载程序负责同步。 - 使用没有 holder 的单例是急切的初始化,因为一旦 Java 遇到引用
Singleton
的代码,它的所有静态字段都会被解析。它也是线程安全的,因为 class 加载程序负责同步。
有持有人的单身人士。
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(){ }
}
Update 回应@jan 的建议,即这是 What is an efficient way to implement a singleton pattern in Java?. I disagree. I am not asking what is the best way to do it: I am only asking what makes these two specific implementations lazy vs eager loading. Answers like xyz's 的重复,广泛地解决懒惰与急切的问题,但不是通过对比我尝试的两个例子检查(或使用相同的关键字,这就是为什么它从未出现在我的初始搜索中)。
作为对@Sriram 的回应,这是我的测试来证明哪个是急切加载还是延迟加载。
使用 holder 延迟加载
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.