单例模式 7 种实现方式对比表

序号 实现方式 线程安全 懒加载 性能 防止反射破坏 防止序列化破坏 代码复杂度 适用场景
1 饿汉式 单线程环境简单应用
2 懒汉式(线程不安全) 单线程环境,性能要求高
3 懒汉式(方法同步) 多线程但性能要求不高
4 双重检查锁(DCL) 多线程,性能要求高
5 静态内部类 推荐使用,兼顾性能和懒加载
6 枚举 最佳实践,保证绝对单例
7 ThreadLocal单例 线程内安全 线程池环境,线程隔离单例

详细说明

1. 饿汉式

java 复制代码
public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();
    private EagerSingleton() {}
    public static EagerSingleton getInstance() {
        return instance;
    }
}

优点 : 实现简单,线程安全
缺点: 类加载时就初始化,浪费内存

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

java 复制代码
public class LazySingleton {
    private static LazySingleton instance;
    private LazySingleton() {}
    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

优点 : 懒加载,需要时才创建
缺点: 线程不安全,可能创建多个实例

3. 懒汉式(方法同步)

java 复制代码
public class SyncSingleton {
    private static SyncSingleton instance;
    private SyncSingleton() {}
    public static synchronized SyncSingleton getInstance() {
        if (instance == null) {
            instance = new SyncSingleton();
        }
        return instance;
    }
}

优点 : 线程安全,懒加载
缺点: 每次获取都加锁,性能差

4. 双重检查锁(DCL)

java 复制代码
public class DCLSingleton {
    private volatile static DCLSingleton instance;
    private DCLSingleton() {}
    public static DCLSingleton getInstance() {
        if (instance == null) {
            synchronized (DCLSingleton.class) {
                if (instance == null) {
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }
}

优点 : 线程安全,懒加载,性能较好
缺点: JDK1.5+才完全安全,实现稍复杂

5. 静态内部类

java 复制代码
public class InnerClassSingleton {
    private InnerClassSingleton() {}
    private static class SingletonHolder {
        private static final InnerClassSingleton instance = new InnerClassSingleton();
    }
    public static InnerClassSingleton getInstance() {
        return SingletonHolder.instance;
    }
}

优点 : 线程安全,懒加载,性能好
缺点: 无法防止反射破坏

6. 枚举(最佳实践)

java 复制代码
public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() {
        // 业务方法
    }
}

优点:

  • 绝对防止反射破坏

  • 自动处理序列化

  • 线程安全

  • 代码简洁

缺点: 不是懒加载,枚举类加载时就初始化

7. ThreadLocal单例

java 复制代码
public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> threadLocal =
        ThreadLocal.withInitial(ThreadLocalSingleton::new);
    
    private ThreadLocalSingleton() {}
    
    public static ThreadLocalSingleton getInstance() {
        return threadLocal.get();
    }
}

优点 : 线程内单例,适合线程池环境
缺点: 每个线程有自己的实例,不是真正的全局单例

选择建议

  1. 简单场景:饿汉式

  2. 标准需求:静态内部类(推荐)

  3. 严格要求:枚举(最佳实践)

  4. 线程隔离:ThreadLocal单例

  5. 历史遗留:DCL(注意volatile关键字)

注意事项

  1. 反射攻击防护:只有枚举能天然防止反射破坏,其他方式需要额外防护代码

  2. 序列化问题:实现Serializable接口时,需要添加readResolve()方法

  3. 克隆防护:重写clone()方法,抛出CloneNotSupportedException

  4. 多类加载器:自定义类加载器可能破坏单例,需注意类加载器隔离

相关推荐
xbgRS2 小时前
springboot的自动装配
java·spring boot
嘻哈∠※9 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_79810 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander25811 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅11 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
极创信息13 小时前
系统安全隐患全方位排查方案:标准化渗透测试全流程
java·opencv·struts·数据挖掘·eclipse·语音识别·hibernate
汉字萌萌哒13 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
喜欢的名字被抢了13 小时前
程序出问题怎么查,以及如何让它不掉线
java·运维·数据库
数据知道14 小时前
反序列化漏洞:Java、PHP、Python 三条线各讲透
java·网络·python·安全·网络安全·php
2601_9499506314 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐