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

单例模式总结

单例模式,最常见的有两种单例模式,饿汉式和懒汉式,如下:

/** * 饿汉式 */ public class SingletonHungry { //单例对象 private SingletonHungry instance = new SingletonHungry(); //私有构造方法 private SingletonHungry(){} public SingletonHungry getInstance(){ return instance; } }
/** *懒汉式 */ public class SingletonLazy { //单例对象 private static SingletonLazy instance; //私有构造方法 private SingletonLazy(){} //静态工厂方法 public static SingletonLazy getInstance(){ if(instance==null){ instance = new SingletonLazy(); } return instance; } }

上述两种方式都存在着线程不安全的情况,以懒汉式为例,instance对象还没创建的时候,如果两条线程访问getInstance方法,进入了if条件,同时都new的话,就产生了两个实例。

解决方案:synchronized加双重检测

/** *synchronized加双重检测 */ public class SingletonSyn { //单例对象 private static SingletonSyn instance; //私有构造函数 private SingletonSyn(){} //静态工厂方法 public static SingletonSyn getInstance(){ //双重检测 if(instance == null){ synchronized (SingletonSyn.class){ if(instance==null){ instance = new SingletonSyn(); } } } return instance; } }

解析:双重检测的好处,就是首先判断instance为空,有两条线程都可以进入了这判断条件,当一条线程执行完了getInstance方法,释放了锁, 然后另一条线程已经进入第一层判断,这时可获取锁,如果在synchronized代码块不做判断就有产生了一个实例,就不是单例了

存在问题:此时仍难不是线程安全的,因为JVM会进行指令重排,new一个对象的步骤是1.分配对象的内存空间2.初始化对象3.设置instance指向刚分配的实例 *有些时候JVM会把其顺序条为1,3,2,3过程执行了对象就不等于null,所以就存在下边这种情况,线程A在new对象,线程B在第一个条件判断 * 当线程A先执行了1,3,此时线程B刚好判断为false,那么线程B直接返回instance,这是一个没创建好的对象,所以就出错了

解决方案:单例加上volatile关键字防止指令重排

/** *线程安全的单例代码 */ public class SingletonSyn { //单例对象 private volatile static SingletonSyn instance; //私有构造函数 private SingletonSyn(){} //静态工厂方法 public static SingletonSyn getInstance(){ //双重检测 if(instance == null){ synchronized (SingletonSyn.class){ if(instance==null){ instance = new SingletonSyn(); } } } return instance; } }

存在问题:此时还会存在一个问题,我们能利用反射仍可获得多个对象

解决办法:用枚举类

/** * 枚举类实现单例模式 */ public enum SingletonEnum { INSTANCE; private SingletonEnum() { } public void print(){ System.out.println("hello world"); } } public static void main(String[] args) { SingletonEnum instance = SingletonEnum.INSTANCE; instance.print(); }

至此单例一些情况全都介绍完了

http://www.cnnetsun.cn/news/3715736.html

相关文章:

  • 利用美国教育邮箱低成本获取AI开发工具权限:Dify部署与Claude注册实战指南
  • 2026专业的ai建站机构哪个好,看看有没有你的心头好?
  • 802.11无线权威指南读书笔记(12)直接序列物理层DSSS与HR/DSSS(802.11b)
  • 抖音批量下载工具终极指南:3步轻松保存无水印高清视频
  • 3步GPU显存稳定性终极指南:memtest_vulkan完整教程与最佳实践
  • 物联网设备安全方案:SE050与STM32F410RB硬件集成
  • TEL F17-621561-2 超声波流量计
  • Windows系统MySQL 8.0本地安装配置与连接测试完整指南
  • 医疗压力测绘系统市场发展格局分析及投资战略规划报告2026年版
  • 基于Arduino与LabVIEW的多路数据采集系统设计与实现
  • 丙酮酸激酶(PK)催化机制与 LDH 偶联 NADH 比色检测原理
  • AI客服质检SOP手册(含12类话术违规判定规则+自动打分阈值表)
  • 微服务架构图
  • 终极视频合成指南:ComfyUI-VideoHelperSuite VHS_VideoCombine节点完全解析
  • ssm整合时报错java.lang.ClassNotFoundException:org.springframework.web.bind.MissingMatrixVariableException
  • 使用dplyr高效处理时间序列数据的技巧与实践
  • Linux运维学习路线图:从命令新手到实战工程师的体系化进阶
  • 2026 国产大模型硬核横评|阿里云百炼(通义 Qwen3.7 Max)VS DeepSeek V4-Pro:平台、定价、吞吐、能力、工程落地全方位对比
  • 第三十五周学习生活总结
  • 学工管理系统信息化建设与架构实践
  • 从电视盒子到全能服务器:Amlogic S9xxx系列设备Armbian深度重构实战指南
  • 如何快速掌握字体设计:开源编辑器FontForge完整指南
  • Spring Cloud 搭建
  • UnderReplicatedBlocks处理流程
  • 不同数据库中 VARCHAR 的差异及字符串查询“N”前缀的使用规则
  • C/C++:字符串分割、版本比较
  • Json粘贴为类
  • 算不准,活得好:从“人算不如天算”到“活的系统”
  • 北京展厅设计制作公司推荐与选型指南
  • BERT模型在金融新闻去重中的应用与实践