【JavaEE】单例模式
作者主页:paper jie_博客
本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。
本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将MySQL基础知识一网打尽,希望可以帮到读者们哦。
其他专栏:《MySQL》《C语言》《javaSE》《数据结构》等
内容分享:本期将会分享设计模式中的单例模式
目录
什么是设计模式
什么是单例模式
单例模式的实现方式
饿汉模式
具体代码
代码分解
懒汉模式
懒汉模式 - 单线程
具体代码
代码分析
懒汉模式 - 多线程
问题一: 原子性
改进
问题二: 加锁带来的开销
改进
问题三: 指令重排序
改进:
什么是设计模式
设计模式是咱们程序猿圈子中的一些大佬写出来的,为了规范我们的代码,让我们的代码不至于写的见不得人,可以说使用设计模式就等于给了你一个下限,只要你按照这个模式来写,再怎么样也不至于水到哪去. 就可以把它理解为好比棋谱一般.给了我们一些套路,在遇到什么情况,该什么应对. 我们软件开发中就是有许多常见的问题场景,针对这些问题场景,大佬们就总结出来一些固定的套路给我们这些小萌新使用.
什么是单例模式
单例模式它就是能保证某个类只能创建一个实例,而不能创建多个实例.这一点在很多场景中都需要使用.因为往往这类实例需要的内存空间和开销都比较大,我们就需要限制住创建实例的个数.
单例模式的实现方式
单例模式有许多种实现的方式,不过其中最常见的就是饿汉模式和懒汉模式.
饿汉模式
饿汉模式,顾名思义,对于创建这个实例非常迫切,在类一加载就创建好了.
具体代码
class Singleton {private static Singleton instance = new Singleton();public Singleton getInstance() {return instance;}private Singleton() {}
}
代码分解
1. 这里的instance是静态属性,类属性. 是随着类的加载而创建.因为一个类只有一个类对象,类属性也只有一份,所以这里只能创建一次实例.

2. 在类外需要获取这个实例需要使用getinstance方法来获取,而不是自己再new一个.
![]()
3. 这里在类外再new一个对象会发现编译报错,这是因为这里将它的构造方法设置为私有的,在类外是访问不到.这就保证了只能创建一份实例.

懒汉模式
这里懒汉模式有两种,一种单线程,一种多线程.
懒汉模式 - 单线程
具体代码
class Singleton2 {private static Singleton2 instance = null;public Singleton2 getInstance() {if(instance == null) {return new Singleton2();}return instance;}private Singleton2() {}
}
代码分析
这里不会在类加载的时候直接创建实例,而是将创建实例放到了方法中. 当第一个调用getinstance方法时就会创建出实例.后面再使用这个方法时因为instance不是null后就不会再创建了.

这样的代码也可以保证只创建一次实例. 创建实例的实例就看代码中什么时候使用这个方法.这样创建实例就不是很急迫,只有需要的时候才会创建,所以叫懒汉. 且这样有一个好处就是如果用不到这个实例它就不会创建,遮掩就省了一笔开销.要知道一般单例模式中的实例都需要占很大的内存空间的,加载的时间需要很久,这样子加载的时间省了,空间也省了.
懒汉模式 - 多线程
在上述的单线程中,是没有多线程安全问题的,但是当在多线程协调工作时就会线程不安全.像饿汉模式也是线程安全的,因为它只涉及到读操作,但是懒汉模式涉及到读和写操作.这样就会有线程安全问题.
问题一: 原子性
我们假设有两个线程,t1和t2.它们都需要使用getinstance这样方法. 这里可能就会有一种情况: t1先执行,到t1执行到if()语句判断后它就被调度走了,这时t2调度过来执行.等t2执行完到new一个实例返回后,t1再执行.但是t1执行的时候它还是认为instance是null,于是它就又创建了一个实例.
这里就是因为这些操作没有具有原子性(当然这里是伪原子,只是针对t2这个线程来说)

改进
我们这里就需要用到我们的加锁操作了.将相关代码加锁!
class Singleton1 {private static Singleton1 instance = null;public Singleton1 getInstance() {synchronized (Singleton1.class) {if (instance == null) {return new Singleton1();}return instance;}}private Singleton1() {}
}
问题二: 加锁带来的开销
这里看似处理了问题,但是还有其他的毛病.这里我们发现加锁操作其实只有第一次创建对象(也就是改操作)是需要的,后面的操作都不需要,但是我们还是需要进行锁竞争,这里就是导致开销比较大.
改进
这里我们在外头再加上一层if判断即可. 这里的第一个if就是判断需不需要加锁,第二个if就是在加锁操作下判断有没有创建实例.
class Singleton1 {private static Singleton1 instance = null;public Singleton1 getInstance() {if(instance == null) {synchronized (Singleton1.class) {if(instance == null) {return new Singleton1();}}}return instance;}private Singleton1() {}
}
问题三: 指令重排序
对于new这个代码,有三个操作: 1. 申请一块内存. 2. 在这块内存中调用构造方法来初始化这个实例. 3. 将这个内存地址赋值到instance中. 这里一般来说我们就是按顺序执行.但是JVM中可能就会给你优化,也就是指令重排序. 可能就会出现 1 3 2这种顺序. 这里就会发生问题:
这里也假设有t1和t2, 当t1一直执行到new操作的3后,这时就被CPU调度走了,让t2进来执行代码.当t2执行到第一个if判断时,发现instance不为null,他就直接返回了.但是这里的instance是一块没有被初始化的空间地址,这就会导致t2接下来的逻辑发生问题.

改进:
这里我们就需要用到我们的volatile.它有两个作用:
1. 保证内存可见性. 它可以强制让JVM不进行代码优化,保证每次都到内存中读取变量.
2. 禁止指令重排序. 针对volatile修饰的这个变量的相关指令,JVM是不可以优化重排序的.
class Singleton1 {private volatile static Singleton1 instance = null;public Singleton1 getInstance() {if(instance == null) {synchronized (Singleton1.class) {if(instance == null) {return new Singleton1();}}}return instance;}private Singleton1() {}
}
相关文章:
【JavaEE】单例模式
作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&…...
第十五届蓝桥杯模拟赛(第二期 C++)
俺自己做的噢,还未核实答案,若有差错,望斧正。 第一题 小蓝要在屏幕上放置一行文字,每个字的宽度相同。小蓝发现,如果每个字的宽为 36 像素,一行正好放下 30 个字,字符之间和前后都没有任何空隙…...
关于Unity中字典在Inspector的显示
字典在Inspector的显示 方法一:实现ISerializationCallbackReceiver接口 《unity3D游戏开发第二版》记录 在编辑面板中可以利用序列化监听接口特性对字典进行序列化。 主要继承ISerializationCallbackReceiver接口 实现OnAfterDeserialize() OnBeforeSerialize() …...
使用Plex结合cpolar搭建本地私人媒体站并实现远程访问
文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频,已经算是生活中稀松平常的场景了,特别是各…...
svn合并冲突时每个选项的含义
合并冲突时每个选项的含义 - 这个图片是 TortoiseSVN(一个Subversion(SVN)客户端)的合并冲突解决对话框。当你尝试合并两个版本的文件并且出现差异时,你需要解决这些差异。这个对话框提供了几个选项来处理合并冲突&…...
指针、数组与函数例题3
1、字符串复制 题目描述 设计函数实现字符串复制功能,每个字符串长度不超过100,不要使用系统提供的strcpy函数 输入要求 从键盘读入一个字符串到数组b中,以换行符结束 输出要求 将内容复制到另一个数组a中,并分别输出数组a和…...
ThreeJs样例 webgl_shadow_contact 分析
webgl_shadow_contact 官方样例中,对阴影的渲染比较特殊,很值得借鉴,学习渲染阴影的思路;这个例子中对阴影的渲染,并没有使用任何光源,没有用shadowmap的常规方式 渲染阴影;而是使用了深度材质T…...
Nginx(缓冲区)
先来思考一个问题,接入Nginx的项目一般请求流程为:“客户端→Nginx→服务端”,在这个过程中存在两个连接:“客户端→Nginx、Nginx→服务端”,那么两个不同的连接速度不一致,就会影响用户的体验(…...
MQTT协议理解并实践
MQTT是一个轻量的发布订阅模式消息传输协议,专门针对低带宽和不稳定网络环境的物联网应用设计 MQTT协议根据主题来分发消息进行通信,支持通配符匹配,可以低开销的使用数百万Topic进行一对一,一对多双向通信。 协议特点 1. 开放…...
实现一个简单的网络通信下(udp)
时间过去好久了,先回忆一下上一篇博客的代码!! 目前来看,我们客户端发一条消息,我服务器收到这一条消息之后呢,服务器也知道了是谁给我发来的消息,紧接这就把这条消息放进buffer当中,…...
Linux中office环境LibreOffice_7.6.2下载
阿里云盘:LibreOffice_7.6.2 使用:下载的文件为exe文件,双击exe文件即可获取到文件 LibreOffice_7.6.2安装: 解压:tar -zxvf LibreOffice_7.6.2_Linux_x86-64_rpm.tar.gz 移动到RPMS目录:cd LibreOffice_7…...
Linux快捷控制
Linux快捷控制 工具安装 yum -y install lrzsz wget curl net-tools git防火墙 systemctl status firewalld.service systemctl stop firewalld.service systemctl disable firewalld.service宝塔 yum install -y wget && wget -O install.sh https://download.bt.…...
免费插件集-illustrator插件-Ai插件-重复复制-单一对象页面排版
文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件>重复复制4.总结 1.介绍 本文介绍一款免费插件,加强illustrator使用人员工作效率,进行制卡专用分层分色。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/8789050…...
GO基础之变量与常量
标识符与关键字 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名、常量名、函数名等等。 Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头。 举几个例子:abc, _, _123, a123。 关键字 关键…...
Docker Compose简单入门
Docker Compose 简介 Docker Compose 是一个编排多容器发布式部署的工具,提供命令集管理容器化应用的完整开发周期,包括服务构建,启动和停止。 Docker Compose 真正的作用是在一个文件(docker-compose.yml)中定义并运…...
使用 PHPMailer 实现邮件的实时发送
💂 个人网站:【 海拥】【神级代码资源网站】【办公神器】🤟 基于Web端打造的:👉轻量化工具创作平台💅 想寻找共同学习交流的小伙伴,请点击【全栈技术交流群】 今天我们利用GitHub上20K星星的项目 PHPMailer…...
在Spring Boot中使用JavaMailSender发送邮件
用了这么久的Spring Boot,我们对Spring Boot的了解应该也逐步进入正轨了,这篇文章讲的案例也在我们的实际开发中算是比较实用的了,毕竟我们完成注册功能和对用户群发消息,都可以采用到邮箱发送功能,往下看,…...
python动态圣诞下雪图
运行图片 代码 import pygame import random# 初始化Pygame pygame.init()# 创建窗口 width, height 800, 600 screen pygame.display.set_mode((width, height)) pygame.display.set_caption(Christmas Tree)# 定义颜色 GREEN (34, 139, 34) RED (255, 0, 0) WHITE (255…...
随心玩玩(十)git
写在前面:研究生一年多了,一直浑浑噩噩的,在深度学习的泥潭挣扎了好久,终于走出了精神内耗的泥潭…好久没有写博客了,决定重新捡起来…记录一下学习吧~ 之前写了一篇git的博客,【github 从0开始的基本操作…...
每日一练【盛最多水的容器】
一、题目描述 11. 盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&…...
Android 11开发避坑:为什么你的App获取的Wifi MAC地址总是变?手把手教你配置固定MAC
Android 11开发实战:彻底解决Wifi MAC地址随机化问题最近在开发一个设备管理系统时,遇到了一个棘手的问题:我们的App在Android 11设备上获取的Wifi MAC地址每次都不一样,导致基于MAC地址的设备识别功能完全失效。经过一周的深入研…...
告别C盘战士!ArcGIS 10.6安装路径选择与磁盘空间优化全攻略
告别C盘战士!ArcGIS 10.6安装路径选择与磁盘空间优化全攻略当GIS初学者第一次安装ArcGIS 10.6时,往往会被其庞大的安装体积所震惊。许多用户习惯性地点击"下一步",结果发现C盘空间被迅速吞噬,系统运行变得迟缓。本文将深…...
基于声卡与电流互感器的安全交流功率测量系统设计与实践
1. 项目概述:用声卡安全测量交流功率我一直对各种测量技术抱有浓厚的兴趣,毕竟“测量即认知”这句老话在今天依然适用。对于电力消耗和产出,没有什么比直接测量更能说明问题了。交流功率的测量,核心在于同时获取电压和电流的瞬时值…...
FeHelper前端助手:30+开发工具集,让你的浏览器变身效率神器
FeHelper前端助手:30开发工具集,让你的浏览器变身效率神器 【免费下载链接】FeHelper 😍FeHelper--Web前端助手(Awesome!Chrome & Firefox & MS-Edge Extension, All in one Toolbox!) 项目地址:…...
荣耀出征官方网站下载正版手游 翅膀养成细节玩法全方位讲解
玩荣耀出征的玩家都清楚,翅膀不仅是角色的颜值象征,更是提升整体战力的核心途径。很多新手玩家只顾着升级、刷装备,完全忽略翅膀养成,导致等级很高但战力始终上不去。还有不少玩家胡乱合成、盲目进阶,浪费了大量稀有翅…...
厨房空调技术白皮书:从风冷到水冷,制冷系统在厨房场景中的工程化演进
厨房空调是暖通行业近三年技术迭代最密集的细分品类。从最初的"凉霸"(本质是风扇),到风冷分体式,再到水冷一体式,每代技术都在解决上一代没有覆盖的用户痛点。本文以工程技术视角,梳理四代厨房制…...
终极Chrome画中画扩展:如何在浏览器中实现高效视频多任务处理
终极Chrome画中画扩展:如何在浏览器中实现高效视频多任务处理 【免费下载链接】picture-in-picture-chrome-extension 项目地址: https://gitcode.com/gh_mirrors/pi/picture-in-picture-chrome-extension 想要在浏览网页、处理文档的同时继续观看视频内容吗…...
INT8量化下TVA注意力对齐精度保障方案
重磅预告:本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容,该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…...
二十六.签名与脚本(1)--脚本介绍
1.区块链脚本介绍在之前的章节中,我们了解了签名与验证相关,但是btc的交易数据,签名和验证,不是单纯的,还有脚本深度参与其中。我们从开始来:bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletT…...
告别DLL缺失烦恼!Visual C++运行库合集一键搞定Windows应用依赖问题
告别DLL缺失烦恼!Visual C运行库合集一键搞定Windows应用依赖问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经在打开某个软件或游戏时…...
