Java 单例与双例模式实现
单例模式确保全局唯一实例;双例模式(罕见)维护固定数量(2)的实例池,按需随机分发。本文给出生产级单例四种写法、双例实现、线程安全分析、适用场景。
单例模式四大写法
| 模式 | 代码骨架 | 优点 | 缺点 |
| 饿汉式 | private static final Instance INSTANCE = new Instance(); | 类加载时创建,天然线程安全,无锁开销 | 类加载即占内存,无法延迟 |
| 懒汉式(同步方法) | synchronized static getInstance() { if (null) new ... } | 延迟加载 | 每次获取加锁,性能差 |
| 双重检查锁 (DCL) | volatile Instance; if (null) synchronized { if (null) new } | 延迟 + 高性能 | 需 volatile 禁止指令重排,JDK 5+ 有效 |
| 静态内部类 | static class Holder { static final Instance INSTANCE = new Instance(); } | 延迟 + 线程安全 + 简洁 | 无明显缺点,**推荐** |
| 枚举单例 | enum Instance { INSTANCE; } | 防反射/序列化破坏,最简洁 | 无法延迟加载(枚举类加载即实例化) |
双例模式实现
public class Doubleton {
private static final List POOL = new ArrayList<>();
private static final int SIZE = 2;
private static final Random RANDOM = new Random();
static {
for (int i = 0; i < SIZE; i++) POOL.add(new Doubleton());
}
private Doubleton() {}
public static Doubleton getInstance() {
return POOL.get(RANDOM.nextInt(SIZE)); // 随机分发
}
public String getValue(String name) { return name; }
}
关键点解析
- 固定池大小:静态块预创建
SIZE 个实例,生命周期随类加载
- 随机分发:
Random.nextInt(SIZE) 实现简单负载均衡
- 线程安全:静态初始化由 JVM 保证;
Random 为线程安全类
- 扩展性:
SIZE 可配置化为三例、N 例;分发策略可替换为轮询、加权
适用场景对比