Java单例模式的七种实现方式
1. 饿汉式(静态常量)
- 代码示例:
public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {}public static Singleton getInstance() { return INSTANCE; } }
- 特点:
- 线程安全:类加载时自动初始化,无需同步。
- 非懒加载:可能造成资源浪费(若实例未被使用)。
- 适用场景:资源占用小且频繁使用的单例。
2. 饿汉式(静态代码块)
- 代码示例:
public class Singleton {private static Singleton singleton;static { singleton = new Singleton(); }private Singleton() {}public static Singleton getInstance() { return singleton; } }
- 特点:
- 与静态常量实现类似,但代码结构更灵活(如初始化复杂逻辑)。
- 缺点:同样存在非懒加载问题。
3. 懒汉式(非线程安全)
- 代码示例:
public class Singleton {private static Singleton instance;public static Singleton getInstance() {if (instance == null) instance = new Singleton();return instance;} }
- 特点:
- 延迟加载:首次调用时创建实例。
- 线程不安全:多线程环境下可能生成多个实例。
4. 懒汉式(同步代码块/方法)
- 代码示例:
public class Singleton {private static Singleton instance;public static synchronized Singleton getInstance() {if (instance == null) instance = new Singleton();return instance;} }
- 特点:
- 线程安全:通过
synchronized
保证单例性。 - 性能问题:每次调用均加锁,效率较低。
- 线程安全:通过
5. 双重检查锁定(DCL)
- 代码示例:
public class Singleton {private static volatile Singleton instance;public static Singleton getInstance() {if (instance == null) { // 第一次检查synchronized (Singleton.class) {if (instance == null) { // 第二次检查instance = new Singleton();}}}return instance;} }
- 关键点:
volatile
防止指令重排序,确保实例化过程可见性。- 线程安全且高效:仅首次调用加锁。
6. 静态内部类
- 代码示例:
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;} }
- 特点:
- 延迟加载:首次调用
getInstance()
时加载内部类。 - 线程安全:JVM保证内部类初始化的原子性。
- 延迟加载:首次调用
7. 枚举
- 代码示例:
public enum Singleton {INSTANCE;// 其他方法... }
- 特点:
- 天然线程安全:JVM确保枚举实例唯一性。
- 防反射与序列化破坏:无法通过反射或反序列化创建新实例。
- 不支持延迟加载。
总结与最佳实践
- 推荐实现:
- 枚举:最简洁、安全,适合大多数场景。
- 静态内部类:延迟加载且线程安全,兼容旧JDK。
- 避免使用:
- 非线程安全的懒汉式(多线程环境)。
- 同步方法/代码块(性能敏感场景)。
- 扩展场景:
- ThreadLocal:需每个线程独立实例时使用。
- 容器式单例:管理多个单例对象时适用。
通过合理选择实现方式,可平衡性能、线程安全与代码简洁性。