news 2026/5/1 8:50:24

单例模式详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
单例模式详解

一、什么是单例模式?

单例模式(Singleton Pattern)是一种创建型设计模式,核心思想是:
保证一个类在整个程序运行期间,有且仅有一个实例,并提供一个全局访问点来获取这个唯一实例。

核心特点

  1. 唯一实例:类只能被实例化一次。
  2. 全局访问:提供一个静态方法,让外部能方便地获取这个唯一实例。
  3. 私有构造:构造方法私有化,禁止外部通过new关键字创建实例。

适用场景

  • 配置类(如数据库连接配置、系统配置)
  • 日志类(全局统一日志输出)
  • 线程池、缓存、连接池等需要共享资源的场景

二、单例模式的实现方式

单例模式有多种实现方式,各有优缺点,下面是常见的几种:

1. 饿汉式(Eager Initialization)

特点:类加载时就创建实例,线程安全,但可能造成资源浪费(如果实例一直没被使用)。

publicclassSingleton{// 类加载时就初始化privatestaticfinalSingletoninstance=newSingleton();// 私有构造privateSingleton(){}// 全局访问点publicstaticSingletongetInstance(){returninstance;}}

2. 懒汉式(Lazy Initialization)

特点:第一次调用getInstance()时才创建实例,节省资源,但非线程安全

publicclassSingleton{privatestaticSingletoninstance;privateSingleton(){}publicstaticSingletongetInstance(){// 非线程安全:多线程下可能创建多个实例if(instance==null){instance=newSingleton();}returninstance;}}

3. 双重检查锁(Double-Checked Locking)

特点:结合了懒汉式的延迟加载和线程安全,是最常用的高效实现方式

publicclassSingleton{// volatile 禁止指令重排,保证多线程下的可见性privatestaticvolatileSingletoninstance;privateSingleton(){}publicstaticSingletongetInstance(){// 第一次检查:避免每次都加锁,提升性能if(instance==null){// 加锁:保证同一时间只有一个线程进入synchronized(Singleton.class){// 第二次检查:防止多个线程同时通过第一次检查后,重复创建实例if(instance==null){instance=newSingleton();}}}returninstance;}}
关键细节
  • volatile关键字
    • 保证变量的可见性:一个线程修改了instance,其他线程能立即看到。
    • 禁止指令重排new Singleton()分为三步(分配内存、初始化对象、引用赋值),volatile防止这三步被重排,避免多线程下获取到未初始化的实例。
  • 双重检查
    • 第一次检查:快速判断,避免每次都进入同步块,提升性能。
    • 第二次检查:在同步块内再次判断,确保只创建一个实例。

4. 静态内部类(Static Inner Class)

特点:利用类加载机制实现延迟加载和线程安全,代码简洁,推荐使用。

publicclassSingleton{privateSingleton(){}// 静态内部类:只有在被调用时才会加载,实现延迟加载privatestaticclassSingletonHolder{privatestaticfinalSingletoninstance=newSingleton();}publicstaticSingletongetInstance(){returnSingletonHolder.instance;}}

5. 枚举(Enum)

特点最简洁、最安全的实现方式,天然防止反射和序列化破坏单例,推荐使用。

publicenumSingleton{INSTANCE;// 唯一实例// 可以添加其他方法publicvoiddoSomething(){// 业务逻辑代码}}// 使用方式Singleton.INSTANCE.doSomething();

三、单例模式的破坏与防护

1. 反射破坏

反射可以通过setAccessible(true)绕过私有构造,创建多个实例。

防护

  • 在构造方法中判断实例是否已存在,若存在则抛出异常。
privateSingleton(){if(instance!=null){thrownewRuntimeException("单例模式禁止反射创建实例");}}
  • 使用枚举实现,天然防止反射破坏。

2. 序列化破坏

如果单例类实现了Serializable接口,反序列化时会创建新的实例。

防护

  • 重写readResolve()方法,返回单例实例。
privateObjectreadResolve(){returninstance;}
  • 使用枚举实现,天然防止序列化破坏。

四、实现方式对比

实现方式线程安全延迟加载性能推荐度
饿汉式⭐⭐⭐
懒汉式
双重检查锁⭐⭐⭐⭐
静态内部类⭐⭐⭐⭐⭐
枚举⭐⭐⭐⭐⭐

最佳实践

  • 追求简洁和安全:使用枚举
  • 追求延迟加载和性能:使用静态内部类双重检查锁

五、总结

  1. 单例模式的核心是保证类只有一个实例,并提供全局访问点,构造方法必须私有化。
  2. 饿汉式线程安全但无延迟加载,懒汉式有延迟加载但非线程安全,双重检查锁和静态内部类兼顾了线程安全与延迟加载。
  3. 枚举是最安全的单例实现方式,能天然抵御反射和序列化破坏,推荐优先使用。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 17:50:30

Java计算机毕设之基于springboot+vue的高校二手市场交易系统基于SpringBoot的校园二手物品交易平台系统(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/4/28 11:38:48

《突破训练瓶颈:参数服务器替代架构效率优化指南》

大规模训练的效率桎梏,本质是参数管理与训练进程的协同断层—传统参数服务器的中心化架构,将参数存储、更新与节点训练强拆分,导致跨节点参数同步时的语义损耗、通信延迟与资源错配,即便堆砌硬件算力,也难以突破“同步…

作者头像 李华
网站建设 2026/4/25 15:56:11

计算机二级报名图片大小压缩,照片怎么改才合规

计算机二级报名上传照片时,很多同学都踩了坑:照片体积过大提交失败,手动改尺寸后比例失调,找工具压缩又怕画质变差通不过审核。计算机二级报名照片有明确规范:背景为白色,标准尺寸 290*400 像素&#xff0c…

作者头像 李华
网站建设 2026/4/30 15:02:42

在 Linux 环境通过命令行上传 IPA 到 App Store,iOS自动化构建与发布

当项目进入自动化阶段后,很多团队会发现构建环境已经迁移到 Linux,但 iOS 发布流程仍然被 macOS 限制住。 代码可以在 CI 里跑,IPA 可以在远程 Mac 或云构建节点生成,但上传 App Store这一步,卡在最后。Transporter 依…

作者头像 李华
网站建设 2026/4/30 12:21:20

Java计算机毕设之基于协同过滤算法的非遗文化交流平台基于SpringBoot3+Vue3的协同过滤算法的非遗文化交流平台(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华