Java 单例模式
一、什么是单例模式
- 定义 :一个类在整个程序中只创建一个实例,全局共享。
- 核心 :私有构造器 + 静态获取实例方法。
- 使用场景:工具类、配置类、线程池、日志对象、Spring Bean 等。
二、单例模式的 3 个要点
- 构造器私有 (禁止外部
new) - 自身持有静态实例
- 提供全局获取方式 (
getInstance()/ 枚举)
三、单例模式 6 种写法(线程安全分类)
1. 饿汉式(静态常量)
类加载就创建,天生线程安全
java
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
- 优点:简单、安全、无锁
- 缺点:类加载就创建,可能浪费内存
- 线程安全:✅
2. 饿汉式(静态代码块)
和静态常量一样,只是初始化放在静态代码块
java
public class Singleton {
private static Singleton instance;
static { instance = new Singleton(); }
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
3. 懒汉式(synchronized 方法)
用的时候再创建,但加锁性能差
java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 优点:懒加载
- 缺点:并发性能极差
- 线程安全:✅(不推荐)
4. 双重检查锁 DCL(推荐)
高性能 + 线程安全 + 懒加载
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:禁止指令重排
- 优点:高性能、懒加载、安全
- 线程安全:✅(推荐)
5. 静态内部类(最完美)
JVM 保证安全,懒加载,无锁
java
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
- 外部类加载 → 不加载内部类
- 调用
getInstance()→ 才加载Holder - 优点:懒加载、高性能、极简
- 线程安全:✅(强烈推荐)
6. 枚举单例(顶级、官方推荐)
Java 语法层天生单例
java
public enum Singleton {
INSTANCE;
public void method() {
// 业务方法
}
}
使用:
java
Singleton.INSTANCE.method();
- 优点:无法反射破坏、无法序列化破坏、代码最简
- 线程安全:✅(最高级)
四、枚举单例 vs 饿汉式(核心区别)
| 特性 | 饿汉式 | 枚举单例 |
|---|---|---|
| 线程安全 | ✅ | ✅ |
| 类加载初始化 | ✅ | ✅ |
| 反射破坏 | ❌ 可破坏 | ✅ 不能破坏 |
| 序列化破坏 | ❌ 可破坏 | ✅ 不能破坏 |
| 代码量 | 多 | 极少 |
| 官方推荐 | ❌ | ✅ |
结论:枚举 = 终极版饿汉式
五、单例模式的 3 种破坏方式(面试重点)
- 反射:可调用私有构造器创建新对象
- 序列化/反序列化:会生成新对象
- 类加载器:不同类加载器可创建多个实例
只有枚举单例不会被破坏!
六、线程安全总结
| 写法 | 线程安全 | 懒加载 | 推荐指数 |
|---|---|---|---|
| 饿汉式 | ✅ | ❌ | ⭐⭐⭐ |
| 懒汉式 synchronized | ✅ | ✅ | ⭐ |
| 双重检查锁 DCL | ✅ | ✅ | ⭐⭐⭐⭐ |
| 静态内部类 | ✅ | ✅ | ⭐⭐⭐⭐⭐ |
| 枚举单例 | ✅ | ❌ | ⭐⭐⭐⭐⭐ |
七、一句话背会(面试万能)
- 单例:全局一个实例,构造私有。
- 饿汉式:类加载创建,简单但浪费内存。
- DCL:必须加 volatile,禁止指令重排。
- 静态内部类:JVM 保证安全,懒加载高性能。
- 枚举单例:最安全、最简单、官方推荐。
需要我继续整理 线程池、锁、volatile、AQS、JVM 全套并发笔记吗?