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

浅谈单例模式

1.什么是单例模式

单例模式是设计模式的一种,那什么是设计模式呢?
欸问得好,设计模式就是对常见的业务场景总结出来的处理方法,相当于一种“套路”,类似于打王者时候,跟这个英雄对线用连招213比较好,跟那个英雄对线用连招123比较好,嗯…就是这样。

2.如何实现单例模式

实现单例模式,也就是实现单例类有两种方法,首先当我们创建一个正常类的时候,我们可以new无数个这个类的对象且不重复,例如下图:
在这里插入图片描述
看到没,student01和student02是不一样的,它们是两个完全不同的对象
但是在单例模式下,也就是单例类,你不管怎么实例化,最终实例化出来的对象完全唯一。
那么如何实现单例类呢?步骤如下:

1.在类中定义一个static修饰的变量就可以保证这个变量全局唯一(单例)
2.构造方法私有化(防止外部new对象)(那怎么外部实例这个类呢?)
3.设置一个get方法取获取对象,用static修饰,这样外部类就可以通过类名.get的方式调用

具体的实现方法有两种:“饿汉模式”和“懒汉模式”,我们下面逐一介绍:

2.1饿汉模式

代码实现:
在这里插入图片描述
按上面步骤写就是这样,接下来我们在多线程环境测试一下:
在这里插入图片描述
看,是不是外部类无法new新对象,只能用类的静态方法get获取,接下来我们删去new和打印的两行代码,测试十个线程get对象是不是同一个
在这里插入图片描述
Look!就是同一个!这个结果我已经测试了六遍了,你不服可以复制一下代码回去自己跑一下嘻嘻

2.2懒汉模式

代码实现(别急有反转):
在这里插入图片描述
接下来我们用多线程测试一下:
在这里插入图片描述

OK眼尖的大佬已经发现了多线程环境中实例化出来的对象不唯一啊,测试结果与预期不符这叫什么,嗯这就是出现了线程安全问题

问题原因详解:根本原因是cpu调度问题,线程是抢占式执行的,例如现在有两个线程,A和B,当A首先进get方法美滋滋拿到instance后!还没把instance 给store呢,线程B也进来了!由于A还没来及store它拿到的instance,instance此时为空!那么B load 的也是空, 嘿B也能通过if语句,B又get一个instance!问题就出现了…

如何解决:给那段代码加锁,确保A没执行完其他线程例如B不许进来,就好了,如下:
在这里插入图片描述
但是,还有个问题:这一加锁,每个线程进来在cpu中都要lock 然后再unlock,效率很低啊,因为这个锁我们只用一次啊,当第一次instance成功store后,后面线程load的都是那个对象,就进不去if从句,所以我们。。。。
再加个判断条件,当instance不为空直接返回就好了,不用进来再加锁再判断,然后发现不为空再返回。

于是,完整代码如下(无反转版):
在这里插入图片描述
史称DCL (Double Check Loak)双重检查锁
当然真理解不了就算了,不加,代码也能跑过,随缘。

2.3缘起

那么为什么一个叫饿汉模式一个叫懒汉模式呢,其实看代码就知道了:
饿汉模式中第一步直接就把那个static修饰的变量给实例化了,就像一个饿了很久的流浪汉,库库吃

第二个懒汉模式就是第一步我只声明一下,我懒得实例化,等到后面再说~所以叫懒汉

嗯。。。。。。。。。。。。。。。。。。。。其实我一直觉得好牵强,不如一个叫极简模式一个叫炫技模式(我的评价是)
。。。。。。。
那么好本篇写完了,(好厉害),当然了主播是实力派(OK)(KO)。


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

相关文章:

  • 谷歌开放语音命令数据集,助力初学者踏入音频识别领域
  • Flutter:打包apk,安卓版本更新(二)
  • 【深度学习】深度(Deep Learning)学习基础
  • 开放词汇检测新晋SOTA:地瓜机器人开源DOSOD实时检测算法
  • DAY15 神经网络的参数和变量
  • VSCode Live Server 插件安装和使用
  • 【AI图像生成网站Golang】项目测试与优化
  • 电脑上怎么运行手机APP(电脑上运行手机APP的4种方法)
  • 深入解析java.lang.NumberFormatException异常及解决方法
  • Ubuntu交换区(Swap)扩容方法
  • linux 查找当前目录下大于10G的目录,并删除它们
  • mac电脑可以使用的模拟器
  • 网络术语MSS/MTU/TSO/Len说明
  • ABP vNext多租户配置及通过域名方式解析租户的实现
  • 构建一个rust生产应用读书笔记6-拒绝无效订阅者02
  • 深入探索Vue.js中的methods选项:事件处理与业务逻辑的核心机制
  • Android Compose Modifier
  • 简单了解一下 Go 语言的构建约束?
  • ES6中的map和set
  • PHP代码审计学习(一)--命令注入
  • Linux 常用命令功能解析:man、apropos、locate 和 which
  • OpenAI 与 ChatGPT 的关系解析
  • CSS系列(13)-- 预处理器详解
  • 2024告别培训班 数通、安全、云计算、云服务、存储、软考等1000G资源分享
  • .Net Core框架创建一个Windows服务类型的应用程序
  • 基于 uniapp 开发 android 播放 webrtc 流