并发编程下的单例设计模式
饿汉式
/**
* @author BNTang
*/
public class Singleton {
/**
* 没有延迟加载,好长时间不使用,影响性能
*/
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
特点
- 线程安全性: 在加载的时候已经被实例化,所以只有这一次是线程安全的
- 懒加载: 没有延迟加载,好长时间不使用,影响性能
懒汉式 + 同步方法
/**
* @author BNTang
*/
public class SingletonTwo {
private static SingletonTwo instance = null;
private SingletonTwo() {
}
public synchronized static SingletonTwo getInstance() {
if (instance == null) {
instance = new SingletonTwo();
}
return instance;
}
}
特点
- 直接在方法上进行加锁
- 锁的力度太大,性能不是太好
- synchronized,退化到了串行执行
Double-Check-Locking
/**
* @author BNTang
*/
public class SingletonThree {
private static volatile SingletonThree instance = null;
private SingletonThree() {
}
public static SingletonThree getInstance() {
// Double-Check-Locking, DCL
if (instance == null) {
synchronized (SingletonThree.class) {
if (instance == null) {
instance = new SingletonThree();
}
}
}
return instance;
}
}
特点
- 保证了线程安全
- 如果实例中存在多个成员属性,由于在代码执行过程当中, 会对代码进行重排, 重排后, 可能导致另一个线程获取对象时初始化属性不正确的情况
加 volatile
创建对象步骤
memory = allocate(); // 1:分配对象的内存空间
ctorInstance(memory); // 2:初始化对象
instance = memory; // 3:设置 instance 指向刚分配的内存地址
memory = allocate(); // 1:分配对象的内存空间
instance = memory; // 3:设置 instance 指向刚分配的内存地址
// 注意,此时对象还没有被初始化!
ctorInstance(memory); // 2:初始化对象
重排问题
Holder
/**
* @author BNTang
*/
public class SingletonFour {
private SingletonFour() {
System.out.println("SingletonFour 初始化了");
}
/**
* 第一次使用到的时候才去执行, 只执行一次
*/
private static class Holder {
private static SingletonFour instance = new SingletonFour();
}
public static SingletonFour getInstance() {
return Holder.instance;
}
}
特点
- 它结合了饿汉模式, 安全性,也结合了懒汉模式懒加载。不会使用 synchronized 所以性能也有所保证
- 声明类的时候,成员变量中不声明实例变量,而放到内部静态类中
- 不存在线程安全问题
- 懒加载
反序列化问题
// 该方法在反序列化时会被调用
protected Object readResolve() throws ObjectStreamException {
System.out.println("调用了readResolve方法!");
return Holder.instance;
}
枚举的方式创建单例
/**
* @author BNTang
*/
public enum SingletonFive {
/**
* 单值的枚举就是一个单例
*/
INSTANCE;
private static int a = 0;
public static void add() {
a++;
System.out.println(a);
}
public static SingletonFive getInstance() {
return INSTANCE;
}
}
特点
- 不存在线程安全问题
- 没有懒加载
enum 加延迟加载方式
/**
* @author BNTang
*/
public class SingletonSix {
private SingletonSix() {
}
private enum Holder {
INSTANCE;
private SingletonSix instance = null;
Holder() {
instance = new SingletonSix();
}
private SingletonSix getInstance() {
return instance;
}
}
public static SingletonSix getInstance() {
return Holder.INSTANCE.getInstance();
}
}
特点
- 没有线程安全问题
- 懒加载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具