1. 单例模式的核心概念单例模式Singleton Pattern是设计模式中最简单但应用最广泛的一种模式。它的核心思想是确保一个类只有一个实例并提供一个全局访问点。这种模式在需要控制资源访问、配置管理或线程池等场景中特别有用。我第一次接触单例模式是在开发一个日志系统时。当时系统中有多个模块都在创建日志对象导致日志文件被重复打开和关闭不仅效率低下还可能出现写入冲突。通过引入单例模式我们确保了整个应用只有一个日志实例完美解决了这个问题。2. 单例模式的实现方式2.1 饿汉式单例饿汉式是最简单的实现方式它在类加载时就完成了初始化public class EagerSingleton { private static final EagerSingleton instance new EagerSingleton(); private EagerSingleton() {} public static EagerSingleton getInstance() { return instance; } }这种方式的优点是实现简单线程安全缺点是如果实例未被使用会造成内存浪费。我在一个小型项目中就采用了这种方式因为项目规模小内存消耗不是主要考虑因素。2.2 懒汉式单例非线程安全懒汉式延迟了实例的创建直到第一次调用getInstance()方法public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance null) { instance new LazySingleton(); } return instance; } }这种实现方式在单线程环境下工作良好但在多线程环境下可能会创建多个实例。我曾经在一个测试环境中使用这种方式结果因为并发问题导致系统行为异常。2.3 线程安全的懒汉式为了解决线程安全问题我们可以给getInstance()方法加锁public class ThreadSafeSingleton { private static ThreadSafeSingleton instance; private ThreadSafeSingleton() {} public static synchronized ThreadSafeSingleton getInstance() { if (instance null) { instance new ThreadSafeSingleton(); } return instance; } }虽然这种方式解决了线程安全问题但每次获取实例都需要同步性能较差。在一个高并发的电商项目中我们实测发现这种方式会导致系统吞吐量下降约15%。2.4 双重检查锁定DCL双重检查锁定结合了懒加载和线程安全同时减少了同步的开销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; } }这里volatile关键字很关键它防止了指令重排序导致的初始化问题。我在一个金融项目中就采用了这种方式既保证了线程安全又保持了良好的性能。2.5 静态内部类实现这是我最推荐的一种实现方式它结合了懒加载和线程安全的优点public class InnerClassSingleton { private InnerClassSingleton() {} private static class SingletonHolder { private static final InnerClassSingleton INSTANCE new InnerClassSingleton(); } public static InnerClassSingleton getInstance() { return SingletonHolder.INSTANCE; } }这种方式利用了类加载机制保证线程安全同时实现了懒加载。我在多个生产项目中都采用了这种方式从未出现过问题。3. 单例模式的应用场景3.1 配置管理在应用中配置信息通常只需要加载一次并在全局共享。使用单例模式可以确保所有模块访问的是同一份配置public class AppConfig { private static AppConfig instance; private Properties config; private AppConfig() { // 加载配置文件 config new Properties(); try (InputStream is getClass().getResourceAsStream(/config.properties)) { config.load(is); } catch (IOException e) { throw new RuntimeException(加载配置文件失败, e); } } public static synchronized AppConfig getInstance() { if (instance null) { instance new AppConfig(); } return instance; } public String getProperty(String key) { return config.getProperty(key); } }3.2 数据库连接池数据库连接池通常只需要一个实例来管理所有连接public class ConnectionPool { private static ConnectionPool instance; private ListConnection pool new ArrayList(); private ConnectionPool() { // 初始化连接池 for (int i 0; i 10; i) { pool.add(createConnection()); } } public static synchronized ConnectionPool getInstance() { if (instance null) { instance new ConnectionPool(); } return instance; } public Connection getConnection() { // 获取连接逻辑 } public void releaseConnection(Connection conn) { // 释放连接逻辑 } private Connection createConnection() { // 创建新连接 } }3.3 日志系统日志系统是单例模式的经典应用场景public class Logger { private static Logger instance; private PrintWriter writer; private Logger() { try { writer new PrintWriter(new FileWriter(app.log, true), true); } catch (IOException e) { throw new RuntimeException(无法初始化日志文件, e); } } public static synchronized Logger getInstance() { if (instance null) { instance new Logger(); } return instance; } public void log(String message) { writer.println(LocalDateTime.now() : message); } }4. 单例模式的注意事项4.1 序列化问题如果单例类实现了Serializable接口反序列化时会创建新的实例。解决方法是在类中添加readResolve方法private Object readResolve() { return getInstance(); }我在一个分布式系统中就遇到过这个问题反序列化后的对象与原单例对象不一致导致数据不一致。4.2 反射攻击通过反射可以绕过私有构造函数创建新实例。防御方法是在构造函数中添加检查private Singleton() { if (instance ! null) { throw new IllegalStateException(单例实例已存在); } }4.3 多类加载器环境在多个类加载器环境下每个类加载器可能会创建自己的单例实例。解决方法是指定类加载器或使用上下文类加载器。4.4 单元测试困难单例模式会使单元测试变得困难因为它的状态在整个应用生命周期中持续存在。解决方法是在测试前后重置单例实例或使用依赖注入。5. 单例模式的替代方案虽然单例模式很有用但有时依赖注入框架如Spring提供的单例管理可能是更好的选择。这些框架提供了更灵活的生命周期管理同时保持了单例的特性。在Spring中默认情况下每个bean都是单例的Service public class MyService { // Spring会确保这是单例 }这种方式比传统单例模式更灵活也更易于测试。6. 实际项目中的经验分享在一个电商平台项目中我们使用单例模式管理缓存服务。最初我们采用了双重检查锁定方式但随着业务增长我们发现需要更细粒度的控制。最终我们重构为使用枚举实现public enum CacheManager { INSTANCE; private MapString, Object cache new ConcurrentHashMap(); public void put(String key, Object value) { cache.put(key, value); } public Object get(String key) { return cache.get(key); } }枚举实现单例模式有几个优点绝对防止多次实例化自动处理序列化问题代码更简洁另一个经验是关于单例对象的生命周期管理。在Web应用中单例对象可能会在应用重启后仍然存在于内存中特别是使用静态变量时。我们曾经因此遇到过内存泄漏问题后来通过在ServletContextListener中显式清理单例对象解决了这个问题。单例模式虽然简单但在实际应用中需要考虑很多细节。理解这些细节可以帮助我们更好地应用这个模式避免潜在的问题。
企业数字化 ERP 产品动态
相关推荐
CDFS光盘复制文件指南:只读原理、镜像备份与校验修复 翻出一张十几年前刻的资料盘,塞进光驱,资源管理器里盘符出来了,右键属性第一行写着"文件系统:CDFS"。双击进去,文件名清一色是 ABC123~1.TXT 这种鬼样子;全选拖到硬盘,进度条走到一… · 2026/11/10 22:04:54
Android Studio安装配置全指南:从准备到优化 1. Android Studio安装前的准备工作 作为Android开发的官方IDE,Android Studio提供了代码编辑、调试、性能工具等一系列功能。在开始安装前,我们需要做好以下准备工作: 首先确认你的系统配置是否满足最低要求。对于Windows系统,建… · 2026/11/9 7:21:26
扩散模型对抗样本:原理、攻击方法与防御策略 1. 扩散模型对抗样本基础概念 扩散模型作为当前生成式AI的核心技术,其对抗样本研究呈现出与传统分类模型截然不同的技术特征。传统对抗样本主要针对分类器的决策边界进行攻击,而扩散模型的对抗样本则需要破坏特征提取和生成过程的连贯性。这种差异源于扩… · 2026/11/3 5:57:09
亳州电工证学习怎么报名?怕考不过白交培训费的看过来 亳州电工证学习怎么报名?怕考不过白交培训费的看过来 怕考不过白交培训费?亳州电工证学习怎么报名?这是很多准备报考电工证的朋友最担心的问题。尤其是从事电工相关工作的人员,考证已经不再是可选项,而是硬性要求。但很多人担心,报名后培训不到位、考试… · 2026/11/10 22:04:48
电工证查询要钱吗?多久拿证才靠谱? 电工证查询要钱吗?多久拿证才靠谱? 怕考不过白交培训费?很多同学刚毕业就想着赶紧考个电工证,早点上岗,结果一查资料,发现流程复杂、费用不明,连查询都要钱,心里直打鼓。其实,只要选对机构、走对流程, 多久拿证… · 2026/11/10 22:04:48
嘉兴低压电工证报名,学历不高也能考?考前押题帮你上岸 嘉兴低压电工证报名,学历不高也能考?考前押题帮你上岸 学历不高怕报不上名?嘉兴低压电工证报名其实没那么难,关键是要走对流程、用对方法。我身边就有不少朋友,大专都没上过,照样考下来低压电工证,现在在工地、工厂干得风生水起。今天我就从周口应届工… · 2026/11/10 22:04:48
西藏电工证怎么复审?外省证能转过来吗?考前押题怎么找 西藏电工证怎么复审?外省证能转过来吗?考前押题怎么找 之前考的证在外省能不能转过来?这是很多在西藏打工、换工作的电工最关心的问题。特别是那些在河南、山东、江苏等地考取特种作业操作证的电工,一到西藏就担心自己的证能不能用,复审流程又该怎么走。… · 2026/11/10 22:04:48
坪山区电工证怎么考 实操考试心里没底怕挂科?电子证书帮你稳过 坪山区电工证怎么考 实操考试心里没底怕挂科?电子证书帮你稳过 实操考试心里没底怕挂科,这是很多在坪山区准备考电工证的小伙伴最真实的感受。特别是第一次接触电工实操的,面对各种工具、设备、流程,真的容易紧张。但别担心, 电子证书… · 2026/11/10 22:04:48
西藏电工证怎么复审?工地太忙根本没时间复习考试,多久拿证才是关键 西藏电工证怎么复审?工地太忙根本没时间复习考试,多久拿证才是关键 工地太忙根本没时间复习考试,这几乎是每个特种作业人员的真实写照。尤其是像西藏这样的地区,工地上节奏快、任务紧,很多人拿到电工证后,连复审的时间都挤不出来。而且,很多人对西藏电… · 2026/11/10 22:03:47
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/10 2:16:10
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/10 17:46:39
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/10 17:11:43
丹寨电工证怎么考?内部消息透露报考条件和流程 丹寨电工证怎么考?内部消息透露报考条件和流程 急需特种作业证才能上岗找工作,这是很多电工朋友最真实的焦虑。尤其是像丹寨电工证这样的证书,直接影响你的职业发展和薪资待遇。但你知道吗?很多人都在报考过程中踩坑,有的甚至花了几千块最后白忙一场。今… · 2026/11/10 0:00:13
成都建筑电工证办理郑州报考避坑指南 成都建筑电工证办理郑州报考避坑指南 证书过期了不知道怎么复审延期?别慌!这篇文章手把手带你解决成都建筑电工证办理的难题,顺便避掉郑州报考的那些坑。不管你是刚拿到证的新手,还是准备复审的老电工,这波干货都别错过。… · 2026/11/10 0:00:13
梅州低压电工证怎么考?怕被中介坑?手把手教你全国通用流程 梅州低压电工证怎么考?怕被中介坑?手把手教你全国通用流程 你是不是正为梅州低压电工证发愁?不知道去哪报名,怕被中介骗钱,又担心证书是不是全国通用?其实,这些顾虑都是正常人会有的。今天我就从一个在开封房建工程一线干了几年的电工角度,手把手教你… · 2026/11/10 0:00:13
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 20:19:29
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 19:22:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 17:00:47