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

单例模式及其使用场景

单例模式(Singleton):指在一个系统中某个类只存在一个实例,类中自行实例化,实例向该系统提供统一的访问接口。
单例模式有两种表现形式,饿汉式:类加载时,就进行实例化;懒汉式,第一次引用类时才进行实例化。

饿汉式,代码如图1所示,我们以日志记录器类为例进行说明。

在这里插入图片描述
在类加载时,logger会被初始化。图1中第6行代码私有了构造方法,保证不被外部代码直接实例化。由于构造函数私有,该类无法被继承。通过getInstance方法获得实例,实例再通过info方法统一操作日志文件。

懒汉式

在这里插入图片描述
图2中9—11行,在多个线程同时在这一区块(临界区)执行时,由于线程的走走停停特性,可能会得到多个实例。例如线程一刚好执行完图2第9行代码,此时由于分配给线程一的时间片用完,轮到线程二执行图2中第9行代码后,假如又执行了第10行代码,而后线程一得到了时间片可以继续执行第10行代码,这时就会存在两个logger对象。

解决方式一,如图3,可以解决多线程问题,然而所有线程会排队等锁,这就意味着每次调用getInstance方法时都需要获取锁才会执行,这对调用方可能有影响。

在这里插入图片描述
解决方式二,如图4第4行,静态变量logger被volatile修饰,能保证各个线程中访问logger时的一致性,即如果线程一修改了logger的值,其它线程在访问logger变量的值时会得到修改后的值。但是如果不加图4中第10—11、13—14行代码,也同样会面临图2中遇到的问题,会创建多个logger实例。因此,当多个线程在执行图4中10—14行代码是,只有第一个线程可以进入,创建完实例后离开,而后在排队等待锁的第二个线程获得锁进入10—14行代码块,此时因为volatile关键字的作用,线程二访问到的logger变量已经不为空,因11,13行代码对logger进行了判断,就不会再创建新的实例。在排队等待锁的第三、四、…等线程情况与第二线程类似,此时,如果再有线程进入getInstance方法,图4中的第9、15行将会判断logger是否为空,如果不为空就不会去排队等待进入10—14行代码的锁,这样,后面的线程在执行gelInstance方法时的速度就会得到提高,而不会引起调用方阻塞。

在这里插入图片描述
使用场景:唯一序列;只能允许一个线程访问(如计数器,确保线程安全);创建一个对象需要消耗的资源多(如写日志)等。


http://www.kler.cn/a/105044.html

相关文章:

  • RSAUtil 前端 JavaScript JSEncrypt 实现 RSA (长文本)加密解密
  • 【20年VIO梳理】
  • SpringMVC 异常处理器
  • 详解Java堆的应用场景,思路分析,代码实现
  • 9.(vue3.x+vite)组件间通信方式之EventBus
  • cmd 命令关闭占用端口
  • 从0开始学云计算之服务器:服务的定义,特点,应用场景,分类
  • AFsim编译-Windows
  • Ubuntu22.04安装,SSH无法连接
  • 数据可视化报表分享:区域管理驾驶舱
  • 如何利用验证链技术减少大型语言模型中的幻觉
  • 【算法题】翻转对
  • 爬虫进阶-反爬破解7(逆向破解被加密数据:全方位了解字体渲染的全过程+字体文件的检查和数据查看+字体文件转换并实现网页内容还原+完美还原上百页的数据内容)
  • Go 开发IDE全览:GoLand VS VSCode全面解析
  • Flink实时写入Apache Doris如何保证高吞吐和低延迟
  • Elasticsearch配置文件
  • YOLOv8训练自己的数据集+常用传参说明
  • 华为eNSP配置专题-路由策略的配置
  • 【机器学习】数据均衡学习笔记
  • 纺织工厂数字孪生3D可视化管理平台,推动纺织产业数字化转型