静态内部类方式是Java中实现线程安全懒加载单例的最佳选择,利用JVM类加载机制保证线程安全且实现延迟初始化;双重检查锁定需正确使用volatile关键字防止指令重排序,适用于追求极致性能的场景;枚举实现能防御反射和序列化攻击,适合对安全性要求极高的组件。

在Java中实现线程安全的懒加载单例模式,关键在于既要保证实例延迟初始化(即“懒加载”),又要防止多线程环境下创建多个实例。下面介绍几种常见且有效的实现方式。
使用双重检查锁定(Double-Checked Locking)
这是最常用的懒加载且线程安全的实现方式,通过volatile关键字和同步块结合来提升性能与安全性。
说明:只在第一次创建实例时加锁,后续调用直接返回已创建的实例,避免每次都进入同步代码块。
示例代码:
立即学习“Java免费学习笔记(深入)”;
public class Singleton {
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确保实例化过程的可见性和禁止指令重排序。
- 两次null检查分别用于减少不必要的同步和防止重复创建。
静态内部类实现(推荐)
利用类加载机制保证线程安全,同时实现真正的懒加载。
原理:JVM保证类的初始化是线程安全的,而内部类只有在被调用时才会加载。
示例代码:
立即学习“Java免费学习笔记(深入)”;
public class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
优点:
- 天然线程安全,无需手动加锁。
- 延迟加载:直到getInstance()被调用才加载内部类并创建实例。
- 代码简洁,无额外开销。
枚举实现(防反射攻击)
Effective Java 推荐的方式,不仅能防止多线程问题,还能防止反射和序列化破坏单例。
示例代码:
立即学习“Java免费学习笔记(深入)”;
public enum Singleton {
INSTANCE;
public void doSomething() {
// 业务方法
}
}
适用场景:
- 需要绝对防止多个实例出现(如反序列化或反射构造)。
- 不追求懒加载极致延迟(枚举实例在类加载时初始化)。
对比总结
双重检查锁定:高效、懒加载明显,但需正确使用volatile。
静态内部类:推荐大多数场景,兼顾线程安全与懒加载,代码清晰。
枚举:最强安全性,适合对单例完整性要求极高的系统组件。
基本上就这些。选择哪种方式取决于你是否需要防御反射、是否追求极致延迟加载,以及代码可读性要求。静态内部类方式在多数项目中是最平衡的选择。










