本文目录导读:

Java中实现线程安全的单例模式有多种方式,以下是几种主流且可靠的方法:
饿汉式(推荐,简单安全)
public class Singleton {
// 类加载时即创建实例,JVM保证线程安全
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
优点:实现简单,天然线程安全
缺点:类加载时就创建实例,可能造成资源浪费
懒汉式(双重检查锁定 - DCL)
public class Singleton {
// volatile关键字禁止指令重排序,保证可见性
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton();
}
}
}
return instance;
}
}
注意:必须使用volatile关键字,否则可能因指令重排序导致返回未初始化完成的实例
静态内部类(推荐,懒加载)
public class Singleton {
private Singleton() {}
// JVM保证类的初始化是线程安全的
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点:
- 懒加载:只有调用
getInstance()时才加载内部类 - 线程安全:由JVM类加载机制保证
- 实现简洁,无同步开销
枚举实现(最安全)
public enum Singleton {
INSTANCE;
// 可以添加其他方法
public void doSomething() {
// ...
}
}
优点:
- 绝对防止反序列化创建新实例
- 防止反射攻击
- 实现最简单,线程安全
CAS实现(无锁)
import java.util.concurrent.atomic.AtomicReference;
public class Singleton {
private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<>();
private Singleton() {}
public static Singleton getInstance() {
for (;;) {
Singleton instance = INSTANCE.get();
if (instance != null) {
return instance;
}
instance = new Singleton();
if (INSTANCE.compareAndSet(null, instance)) {
return instance;
}
}
}
}
| 方法 | 懒加载 | 性能 | 防止反射 | 防止序列化 | 推荐度 |
|---|---|---|---|---|---|
| 饿汉式 | 高 | ||||
| DCL | 中 | ||||
| 静态内部类 | 高 | ||||
| 枚举 | 高 | ||||
| CAS | 中 |
推荐选择:
- 无特殊需求:使用静态内部类方式
- 需要防止反射/序列化:使用枚举方式
- 简单场景:使用饿汉式
这些方法都能确保线程安全,选择哪种取决于具体需求和约束条件。