Java 单例模式
Java 中实现单例模式(Singleton Pattern)主要有以下几种方式,每种方式都有各自的优缺点。下面是对常见实现方式的总结和对比:
🧩 一、饿汉式(Eager Initialization)
1 2 3 4 5 6 7 8 9
| public class Singleton { private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return instance; } }
|
✅ 优点:
- 实现简单。
- 类加载时即创建实例,线程安全。
- 不会出现多线程问题。
❌ 缺点:
- 资源浪费:类加载时就实例化,可能实际不需要用到该实例。
🧊 二、懒汉式(Lazy Initialization,非线程安全)
1 2 3 4 5 6 7 8 9 10 11 12
| public class Singleton { private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
|
✅ 优点:
❌ 缺点:
🧵 三、懒汉式(线程安全,加锁)
1 2 3 4 5 6 7 8 9 10 11 12
| public class Singleton { private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
|
✅ 优点:
❌ 缺点:
- 性能低:每次调用
getInstance()
都要加锁,影响性能。
💡 四、双重检查锁(Double-Checked Locking)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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
防止指令重排。
🧘 五、静态内部类(推荐方式)
1 2 3 4 5 6 7 8 9 10 11
| public class Singleton { private Singleton() {}
private static class Holder { private static final Singleton INSTANCE = new Singleton(); }
public static Singleton getInstance() { return Holder.INSTANCE; } }
|
✅ 优点:
- 延迟加载。
- 线程安全。
- 性能好,无需同步。
- 实现简单。
❌ 缺点:
🔐 六、枚举实现(最安全、最简单)
1 2 3 4 5 6 7
| public enum Singleton { INSTANCE;
public void doSomething() { } }
|
✅ 优点:
- 天生线程安全。
- 防止反射和反序列化攻击。
- 简洁优雅。
❌ 缺点:
- 不支持延迟加载。
- 形式上不同于传统类写法,某些场景下不适用(如需要继承)。
📊 对比总结表:
实现方式 |
线程安全 |
是否懒加载 |
性能 |
是否推荐 |
饿汉式 |
✅ |
❌ |
高 |
❌ |
懒汉式(非线程) |
❌ |
✅ |
高 |
❌ |
懒汉式(同步方法) |
✅ |
✅ |
低 |
❌ |
双重检查锁 |
✅ |
✅ |
高 |
✅ |
静态内部类 |
✅ |
✅ |
高 |
✅✅✅ |
枚举实现 |
✅ |
❌ |
高 |
✅✅✅ |
✅ 推荐使用:
- 如果可以不使用延迟加载 ➤ 枚举方式(最安全)
- 如果需要延迟加载 ➤ 静态内部类方式