Singleton with or without holder = lazy vs eager initialisation?(带或不带持有者的单例=懒惰与急切初始化?)
问题描述
这样正确吗:
- 使用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这样的答案大体上是针对懒惰和渴望的,但不是通过对比我试图检查的两个示例(或者使用相同的关键字,这就是为什么我在最初的搜索中没有出现它)。
推荐答案
作为对@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.
这篇关于带或不带持有者的单例=懒惰与急切初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:带或不带持有者的单例=懒惰与急切初始化?
基础教程推荐
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01