达永编程网

程序员技术分享与交流平台

JAVA单例模式有哪几种,各自的适用场景你明白吗?

单例模式确保一个类仅有一个实例,并提供全局访问点。以下是6种经典实现,每种都有特定适用场景,直接上代码+场景分析


1. 饿汉式(立即加载)

public class EagerSingleton {
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    private EagerSingleton() {} // 私有构造
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

场景

  • 初始化成本低
  • 实例必须提前创建(如配置加载)
  • 资源敏感场景(可能浪费内存)

2. 懒汉式(线程不安全)

public class LazySingleton {
    private static LazySingleton instance;
    private LazySingleton() {}
    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton(); // 多线程下可能重复创建
        }
        return instance;
    }
}

场景

  • 单线程环境(如工具类)
  • 禁止用于多线程

3. 同步方法懒汉式(线程安全)

public class SynchronizedSingleton {
    private static SynchronizedSingleton instance;
    private SynchronizedSingleton() {}
    public static synchronized SynchronizedSingleton getInstance() {
        if (instance == null) {
            instance = new SynchronizedSingleton();
        }
        return instance;
    }
}

场景

  • 简单多线程场景
  • 高并发性能瓶颈(每次调用都加锁)

4. 双重检查锁(DCL)

public class DCLSingleton {
    private volatile static DCLSingleton instance; // volatile禁止指令重排序
    private DCLSingleton() {}
    public static DCLSingleton getInstance() {
        if (instance == null) {
            synchronized (DCLSingleton.class) {
                if (instance == null) {
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }
}

场景

  • 高并发场景(减少锁竞争)
  • JDK 5+环境(依赖volatile语义)

5. 静态内部类(推荐)

public class InnerClassSingleton {
    private InnerClassSingleton() {}
    private static class Holder {
        static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }
    public static InnerClassSingleton getInstance() {
        return Holder.INSTANCE; // 首次调用时加载内部类
    }
}

场景

  • 延迟加载 + 线程安全
  • 主流方案(无锁、代码简洁)

6. 枚举单例(最安全)

public enum EnumSingleton {
    INSTANCE; // 天生单例
    public void doWork() {
        System.out.println("Working...");
    }
}
// 调用:EnumSingleton.INSTANCE.doWork();

场景

  • 绝对防止反射攻击
  • 需要序列化的单例(自动处理序列化)
  • 《Effective Java》推荐写法

场景选择速查表

实现方式

线程安全

延迟加载

防反射

序列化安全

适用场景

饿汉式

简单应用,启动即用

懒汉式(基础)

单线程工具类

同步方法懒汉式

低并发多线程

双重检查锁

高并发性能优化

静态内部类

主流方案,平衡安全与性能

枚举

安全要求最高(框架级单例)

关键结论

优先选 静态内部类(平衡安全与简洁)

需要绝对安全用 枚举

旧版本JDK高并发用 双重检查锁

避免使用基础懒汉式(线程不安全)


单例陷阱

  1. 反射攻击 → 枚举可防御
  2. 序列化生成新实例 → 重写readResolve()或直接用枚举
  3. 多类加载器 → 改用上下文类加载器

代码即答案,按场景选用,拒绝过度设计!

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言