当前位置: 首页 > web >正文

创建型:单例模式

目录

1、核心思想

2、实现方式

2.1 饿汉式

2.2 懒汉式

2.3 枚举(Enum)

3、关键注意事项

3.1 线程安全

3.2 反射攻击

3.3 序列化与反序列化

3.4 克隆保护

4、适用场景


1、核心思想

目的:确保一个类仅有一个实例

功能:供全局访问点(通过静态方法或变量提供全局访问入口),可以选择延迟加载。

优点缺点
严格控制实例数量,节省资源可能隐藏类之间的依赖关系,降低可测试性
全局访问点方便管理共享资源违背单一职责原则(管理自身生命周期)
避免频繁创建销毁对象多线程环境需额外处理同步问题

2、实现方式

2.1 饿汉式

饿汉式:即在初始阶段就主动进行实例化,并时刻保持一种渴求的状态,无论此单例是否有人使用。

特点:类加载时立即创建实例,线程安全但可能浪费资源。

public class EagerSingleton {// static:在类加载时初始化,与类同在;  final:一旦被赋值不能被更改private static final EagerSingleton instance = new EagerSingleton();// 私有构造函数,禁止外部调用创建对象private EagerSingleton() {} public static EagerSingleton getInstance() {return instance;}
}

2.2 懒汉式

懒汉式:在第一次使用时,再进行初始化,防止没有人调用,提前初始化造成的资源浪费。

特点:延迟实例化,需处理线程安全问题。

1> 同步锁版本(不推荐)

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

注意: 变量不能使用final,会导致被初始化为null,之后不可赋值

缺点:线程还没进入方法内,就先加锁排队,造成线程阻塞,资源和时间的浪费。

2> 双重检查锁(Double-Checked Locking)

public class DCLSingleton {// volatile:防止指令重排序,保证变量值在各线程访问时的同步性、唯一性private static volatile DCLSingleton instance;private DCLSingleton() {}public static DCLSingleton getInstance() {if (instance == null) { // 第一次检查,放宽入口,保证线程并发高效性synchronized (DCLSingleton.class) {if (instance == null) { // 第二次检查,加锁同步,保证实例化单次运行instance = new DCLSingleton();}}}return instance;}
}

相比“懒汉模式”​,其实在大多数情况下我们通常会更多地使用“饿汉模式”​,原因在于这个单例迟早是要被实例化占用内存的,延迟懒加载的意义并不大,加锁解锁反而是一种资源浪费,同步更是会降低CPU的利用率,使用不当的话反而会带来不必要的风险。

2.3 枚举(Enum)

特点:天然防止反射和序列化攻击,线程安全(推荐方式)

public enum EnumSingleton {INSTANCE; // 这是一个单例对象public void doSomething() {// 业务方法}
}


3、关键注意事项

3.1 线程安全

多线程环境下需确保实例唯一性(如双重检查锁、枚举等)。

3.2 反射攻击

通过反射可绕过私有构造函数,需额外防护(如枚举或抛出异常)。

攻击示例:

// 反射攻击代码:
Class<?> clazz = Singleton.class;
Constructor<?> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true); // 绕过 private 权限
Singleton hackedInstance = (Singleton) constructor.newInstance(); // 创建新实例!

防御方法:在构造方法中抛异常(检测是否已存在实例,若存在则抛出异常

private Singleton() {if (INSTANCE != null) {throw new IllegalStateException("单例已被创建,禁止反射调用!");}
}

3.3 序列化与反序列化

反序列化可能创建新实例,需实现 readResolve() 方法。

攻击示例:

// 序列化攻击代码:
Singleton instance1 = Singleton.getInstance();
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(instance1);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Singleton instance2 = (Singleton) ois.readObject(); // 新实例!

防御方法:实现 readResolve() 方法,直接返回已有实例,覆盖反序列化逻辑。

public class Singleton implements Serializable {private static final Singleton INSTANCE = new Singleton();private Singleton() {}// 反序列化时直接返回 INSTANCEprotected Object readResolve() {return INSTANCE;}
}

3.4 克隆保护

重写 clone() 方法并抛出异常。

若单例类实现了 Cloneable 接口,并直接使用默认的 clone() 方法(或自定义实现未做防御),攻击者可以通过调用 clone() 创建新实例,破坏单例的唯一性。

如果类不实现 Cloneable 接口,调用 clone() 会抛出 CloneNotSupportedException。

即使类未实现 Cloneable,也可显式重写 clone() 方法禁止克隆:

public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {}public static Singleton getInstance() {return INSTANCE;}// 防御 clone 攻击@Overrideprotected Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException("禁止克隆单例!");}
}

4、适用场景

  • 资源共享:如数据库连接池、线程池。

  • 配置管理:全局配置类避免重复加载。

  • 日志记录:统一日志写入入口。

  • 设备驱动:如打印机唯一控制实例。

http://www.xdnf.cn/news/7124.html

相关文章:

  • 【Retinanet】训练自己的数据集
  • 济南国网数字化培训班学习笔记-第三组-1-电力通信传输网认知
  • node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
  • 【Java ee初阶】jvm(3)
  • 柔性PZT压电薄膜在水下高速通信中的应用
  • Flask-SQLAlchemy_数据库配置
  • LeetCode 每日一题 2025/5/12-2025/5/18
  • Linux配置vimplus
  • Python训练营打卡DAY29
  • C++_数据结构_哈希表(hash)实现
  • 大模型deepseek与知识图谱的实践
  • Java面试场景:从音视频到AI应用的技术探讨
  • 嵌入式硬件篇---拓展板
  • 信奥赛CSP动态规划入门-最大子段和
  • 深入理解Docker和K8S
  • 【ubuntu24.04】pycharm 死机结束进程
  • Docker配置SRS服务器 ,ffmpeg使用rtmp协议推流+vlc拉流
  • 阿克曼-幻宇机器人系列教程4- 建图
  • C#自定义扩展方法 及 EventHandler<TEventArgs> 委托
  • 大语言模型上下文长度:发展历程、局限与技术突破
  • 【RabbitMQ】 RabbitMQ高级特性(二)
  • 2025软考高级信息系统项目管理师英文选择题攻略
  • esp32课设记录(二)lcd屏显示文字与照片
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序源码的去中心化商业扩散研究
  • 智慧园区数据大脑管理平台整体解决方案
  • React中巧妙使用异步组件Suspense优化页面性能。
  • 系统架构设计(十二):统一过程模型(RUP)
  • Spring Boot JWT认证示例项目
  • 【PRB】深度解析GaN中最浅的受主缺陷
  • 基于WebRTC的实时语音对话系统:从语音识别到AI回复