-
介绍
单例模式(singleton pattern),本质是用来控制内存中某个类的实例数量的设计模式。
核心:一个类中有且只有一个实例,并提供该实例的全局访问点。
-
单例各种实现方式的对比
| 实现方式 | 创建对象的时间 | 内存消耗 | 延迟加载 | 适用场景 |
|---|---|---|---|---|
| 饿汉式 | 类加载完成 | 低 | 无final:不支持 | 日志对象、配置对象 |
| 有final:支持 | 线程安全工具类、多线程任务管理器 | |||
| 懒汉式 | 第一次使用时 | 无同步锁:高 | 支持 | 需要大量资源 |
| 有同步锁:低 | 支持 | 且程序启动时不需要的对象 | ||
| 双重检查锁定 | 第一次使用时 | 低 | 支持 | 缓存、防止接口重复调用 |
| 内部静态类 | 第一次使用时 | 低 | 支持 | 数据库连接池、文件系统 |
| 枚举 | 类加载时 | 高 | 不支持 | 大文件处理、码值、共享资源访问 |
-
拓展
-
volatile关键字
volatil用于禁止JVM指令重排,以确保其可见性及有序性
声明为volatile的变量每次使用前都会从主内存中获取
其他线程的修改对本线程可见(可立即感知)
可以保证操作的原子性,不被其他线程干扰
-
final关键字
在单例模式中,final关键字常用于修饰变量
根据JVM类加载的机制,使用了final关键字后,单例对象的创建会被延迟到类加载完成后
并且在多线程环境下也可以避免数据竞争及数据安全等问题
-
transient关键字
transient瞬时关键字用于修饰对象中的变量
常见应用于需要被正反实例化的单例对象中指定无需序列化的变量,如密码、银行卡号等
-
readResolve方法
在执行反序列化后,JVM会自动寻找一个与该对象同类的单例对象进行替换
如果该单例对象没有实现
readResolve()方法,或者该方法返回的对象不是单例对象,那么JVM将无法进行反序列化操作,会抛出InvalidClassException异常
-