单例模式,饿汉与懒汉
文章目录
- 什么是单例模式
- 单例模式的两种形式
- 饿汉模式
- 懒汉模式
- 懒汉模式与饿汉模式是否线程安全
- 懒汉模式的优化
什么是单例模式
单例模式其实就是一种设计模式,跟象棋的棋谱一样,给出一些固定的套路帮助你更好的完成代码。设计模式有很多种,单例模式是在校招当中最爱考的设计模式之一。
单例就指的是单个实例,一个程序如果频繁使用一个对象且作用相同,为了防止多次实例化对象,我们就可以使用单例模式,让类只能创建出一个实例,也就是一个对象,减少开销。
有一些场景本身就是要求某一个概念是单例的,例如JDBC里的DateSores
单例模式的两种形式
在Java中实现单例模式有很多种写法,我们这里重点讲解两种,懒汉模式与饿汉模式。
饿汉模式
饿汉模式,顾名思义,当人非常饿的时候,看见了食物,那种心情是怎么样的迫不及待。饿汉模式非常着急在类进行创建时就已经迫不及待的实例化单例对象了
class Singleton {private static Singleton singleton = new Singleton();public static Singleton getInstance() {return singleton;}
}
根据我们的描述可以写出这样的代码,但是我们发现,单例模式的初心我们并没有达到,单例模式的初心是让类只能实例化一次,此时我们并没有完成需求。我们通过私有化构造方法的方式来防止类的多次实例化:
class Singleton {private static Singleton singleton = new Singleton();public static Singleton getInstance() {return singleton;}private Singleton () {}
}
此时我们单例模式中的饿汉模式就已经完成了,我们可以来测试一下:

懒汉模式
懒汉,所表示的含义并不是我们理解的流浪汉,相反懒表示的是一种从容不迫,是不着急,这种模式与饿汉模式的迫不及待不同,他只有在真正需要使用对象时才实例化单例对象。懒汉模式同样使用私有化构造方法的形式来完成初心,我们来写一下代码:
class SingletonLazy {private static SingletonLazy singletonLazy = null;public static SingletonLazy getInstance() {if(singletonLazy == null) {singletonLazy = new SingletonLazy();}return singletonLazy;}private SingletonLazy () {}
}
懒汉模式与饿汉模式是否线程安全
上面我们完成了懒汉模式与饿汉模式的代码编写,现在我们需要考虑一个问题,上面两个代码,是否线程安全,在多线程下调用getInstance()是否会出现问题。
首先我们来看饿汉模式:
饿汉模式的getInstance()方法为只读操作,所以在多线程下调用不会有什么问题,是安全的。
懒汉模式:
懒汉模式在多线程下,无法保证创建对象的唯一性。
例如两个线程同时调用getInstance()方法,代码的执行顺序可能为:
1、线程一进行判断操作
2、线程二进行判断操作
3、线程一实例化对象
4、线程二实例化对象
这样线程一和线程二都会实例化对象,如果是N个线程可能会实例化N个对象,所以懒汉模式在多线程模式下不安全。
懒汉模式的优化
我们需要对懒汉模式进行优化,使得他在多线程下变得安全,如何操作呢?上面的分析中我们提到了,懒汉模式不安全的原因是,判断操作和new操作没有原子性,那么我们让他具有原子性不就可以了。我们就可以通过加锁来完成需求:
class SingletonLazy {private static SingletonLazy singletonLazy = null;public static SingletonLazy getInstance() {synchronized (SingletonLazy.class) {if(singletonLazy == null) {singletonLazy = new SingletonLazy();}}return singletonLazy;}private SingletonLazy () {}
}
这样就会有锁竞争,不会在出现向刚才那样两个线程同时进行判断的操作,一定是等一个线程new了之后,另一个线程才能竞争到锁进行判断。
我们觉得这样还是不够,不够高效,这样写虽然可以解决安全问题,但是同时也造成了效率的降低,每个线程都需要阻塞等待,但是我们分析一下,只有singletonLazy == null时才需要进行阻塞,当singletonLazy != null时其实就只是单纯的读操作。所以我们在进行优化:
class SingletonLazy {private static SingletonLazy singletonLazy = null;public static SingletonLazy getInstance() {if (singletonLazy == null) {synchronized (SingletonLazy.class) {if(singletonLazy == null) {singletonLazy = new SingletonLazy();}}}return singletonLazy;}private SingletonLazy () {}
}
这样又解决了我们的问题,上面代码中的两个判断条件看着是一样的,但是初心不一样,第一个是为了提高效率,判断是否需要加锁,第二个是为了判断是否需要实例化对象,两行代码看着离这不远,但是中间有一个加锁的操作,执行的时机其实差别很大。
这样就完了?并没有这里还有一个问题:指令重排序
什么是指令重排序呢?
创建一个对象,在jvm中会经过三步
1、创建内存空间
2、调用构造方法
3、将引用指向分配好的内存空间
我们发现,第二步和第三步好像可以进行交换执行顺序,交换之后对结果并没有影响,而这样不影响结果的情况下,可以不按照程序编码的顺序执行语句,提高程序性能的操作,我们称为指令重排序。
这里我们也实力化对象了,所以也可能有指令重排序的操作,例如线程一此时new对象的时候,发生了指令重排序,在没有调用构造方法的情况下进行了分配内存空间,此时系统调度到了线程二,线程二进行判断,此时引用非空就返回,这样我们返回了一个没有调用过构造方法的引用。
如何解决问题呢?我们使用volatile就可以防止指令重排序:
class SingletonLazy {volatile private static SingletonLazy singletonLazy = null;public static SingletonLazy getInstance() {if (singletonLazy == null) {synchronized (SingletonLazy.class) {if(singletonLazy == null) {singletonLazy = new SingletonLazy();}}}return singletonLazy;}private SingletonLazy () {}
}
这样懒汉模式的优化,我们就完成了。
相关文章:
单例模式,饿汉与懒汉
文章目录什么是单例模式单例模式的两种形式饿汉模式懒汉模式懒汉模式与饿汉模式是否线程安全懒汉模式的优化什么是单例模式 单例模式其实就是一种设计模式,跟象棋的棋谱一样,给出一些固定的套路帮助你更好的完成代码。设计模式有很多种,单例…...
Prometheus监控实战之Blackbox_exporter黑盒监测
1 Blackbox_exporter应用场景 blackbox_exporter是Prometheus官方提供的exporter之一,可以提供HTTP、HTTPS、DNS、TCP以及ICMP的方式对网络进行探测。 1.1 HTTP 测试 定义 Request Header信息 判断 Http status / Http Respones Header / Http Body内容 1.2 TC…...
【蓝桥杯集训·每日一题】AcWing 1051. 最大的和
文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴线性DP一、题目 1、原题链接 1051. 最大的和 2、题目描述 对于给定的整数序列 A{a1,a2,…,an},找出两个不重合连续子段,使得两子段中所有数字的和最…...
【Unity工具,简单应用】Photon + PUN 2,做一个简单多人在线聊天室
【Unity工具,简单应用】Photon PUN 2,做一个简单多人聊天室前置知识,安装,及简单UI大厅聊天室简单同步较复杂同步自定义同步最终效果前置知识,安装,及简单UI 【Unity工具,简单学习】PUN 2&…...
程序员增加收入实战 让小伙伴们都加个鸡腿
文章目录前言1️⃣一、发外包平台💁🏻♂️二、朋友介绍✍️三、打造自己的个人IP👋🏿四、混群拉单🤳🏿五、面试拉单💻六、技术顾问🦴七、开发个人项目总结:前言 程序员…...
GPIO四种输入和四种输出模式
GPIO的结构图如下所示: 最右端为I/O引脚,左端的器件位于芯片内部。I/O引脚并联了两个用于保护的二极管。 输入模式 从I/O引脚进来就遇到了两个开关和电阻,与VDD相连的为上拉电阻,与VSS相连的为下拉电阻。再连接到TTL施密特触发…...
ChatGPT能够改变时代吗?一点点思考
都知道ChatGPT的出现对整个世界产生了剧烈的影响,前不久出的ChatGPT4更是在ChatGPT3.5的基础上展现了更强的功能。比如说同一个问题,ChatGPT3.5还是乱答的,ChatGPT4已经能给出正确解了。当然这只能说明技术是进步的。 虽然如此,很…...
Markdown如何使用详细教程
目录 一、Markdown 标题 二、Markdown 段落 三、Markdown 字体 四、Markdown 分隔线 五、Markdown 列表 六、Markdown 引用 七、Markdown 代码 八、Markdown 链接 九、Markdown 图片 十、Markdown 表格 前言 当前许多网站都广泛使用 Markdown 来撰写博客,…...
HTML5庆祝生日蛋糕烟花特效
HTML5庆祝生日蛋糕烟花特效 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>HTML5 Birthday Cake Fireworks</title><style>canvas {position: absolute;top: 0;left: 0;z-index: -1;}</style> </h…...
算法套路四——反转链表
算法套路四——反转链表 算法示例一:LeetCode206. 反转链表 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 初始化pre为空,cur为头指针 pre指针:记录当前结点的前一个结点 cur指针:记录当…...
多线程 (六) wait和notify
🎉🎉🎉点进来你就是我的人了 博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!人生格言:当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔🦾&am…...
React--》状态管理工具—Mobx的讲解与使用
目录 Mobx的讲解与使用 Mobx环境配置 Mobx的基本使用 Mobx计算属性的使用 Mobx监听属性的使用 Mobx处理异步的使用 Mobx的模块化 Mobx的讲解与使用 Mobx是一个可以和React良好配合的集中状态管理工具,mobx和react的关系相当于vuex和vue之间的关系࿰…...
有效的括号长按键入验证外星语词典字符的最短距离用栈实现队列
有效的括号来源:杭哥20. 有效的括号 - 力扣(LeetCode)bool isValid(char * s) {int szstrlen(s);char stack[sz];int k0;for (int i0;i<sz;i){if (s[i]( || s[i][ || s[i]{){stack[k]s[i];}else{if (k0){return false;}else if (s[i]} &am…...
《前端开发者的进阶之路》
前端作为Web开发的重要领域之一,不断地发展和演变着。除了基本的HTML、CSS、JavaScript技能,前端开发者需要掌握更多的进阶知识才能应对不断变化的需求。本文将介绍一些前端的进阶知识,帮助前端开发者进一步提高自己的技能水平。1.框架和库在…...
为什么说网络安全是风口行业?是IT行业最后的红利?
前言 “没有网络安全就没有国家安全”。当前,网络安全已被提升到国家战略的高度,成为影响国家安全、社会稳定至关重要的因素之一。 网络安全行业特点 1、就业薪资非常高,涨薪快 2021年猎聘网发布网络安全行业就业薪资行业最高人均33.77万&…...
使用shell 脚本,批量解压一批zip文件,解压后的文件放在以原zip文件名前10个字符的文件夹中的例子
#!/bin/bash for file in *.zip dofolder$(echo $file | cut -c 1-10)mkdir $folderunzip -q $file -d $folder doneecho "All zip files have been extracted." # 说明: # 1. for循环遍历当前目录下的所有zip文件 # 2. 使用cut命令提取zip文件名前10个字…...
01 | Msyql系统架构
目录MySQL系统架构连接器查询缓存分析器优化器执行器MySQL系统架构 大体来说,MySQL分为Server层和引擎层两部分。 Server层包含链接器、查询缓存、分析器、优化器和执行器,而引擎层负责的是数据的存储和读取,支持InnoDB、Myisam、Memory等多…...
Linux命令---设备管理
Linux setleds命令Linux setleds命令用来设定键盘上方三个 LED 的状态。在 Linux 中,每一个虚拟主控台都有独立的设定。语法setleds [-v] [-L] [-D] [-F] [{|-}num] [{|-}caps] [{|-}scroll]参数:-F:预设的选项,设定虚拟主控台的状…...
前端入门:HTML5+CSS3+JAAVASCRIPT
1、 初识HTML HTML:Hyper Text Markup Language(超文本标记语言) 。 超文本包括:文字、图片、音频、视频、动画等。 1.1、W3C标准 1.2、HTML基本结构 示例: <!-- DOCTYPE:告诉浏览器,我们要使用什么规划,这里是HTML --> …...
【头歌实验】课外作业一:开通ECS及使用Linux命令
文章目录一、完成下列实验并截图二、简要回答“课堂考核”内容三、在头歌、华为云或阿里云官网上,找出自己的课外学习资源,制定小组的课程学习计划、专业学习计划。四、习题1.10一、完成下列实验并截图 1、实验《ECS云服务器新手上路》 https://develo…...
GLM-4-9B-Chat-1M惊艳效果:碳中和白皮书(120页)中的技术路径拆解、时间节点校验与政策匹配度评分
GLM-4-9B-Chat-1M惊艳效果:碳中和白皮书(120页)中的技术路径拆解、时间节点校验与政策匹配度评分 1. 项目背景与核心能力 今天要给大家展示一个让人眼前一亮的技术应用场景——用GLM-4-9B-Chat-1M这个本地部署的大模型,来深度分…...
OpenCVSharp摄像头开发避坑指南:C#实现高清录像+实时滤镜(WinForm版)
OpenCVSharp工业级摄像头开发实战:高清录像与实时滤镜的进阶技巧 在工业视觉检测和实时直播领域,稳定高效地采集视频流是核心需求。C#开发者常选择OpenCVSharp作为计算机视觉开发工具,但实际应用中总会遇到帧率不稳定、资源泄漏或参数配置不当…...
Maven Versions Plugin 使用指南
以下是对你提供内容的补充和整理,形成一篇关于 Maven Versions Plugin 使用指南的文章:Maven Versions Plugin 使用指南 Maven Versions Plugin 是一套用于管理项目版本、依赖版本和父版本的工具集合。它可以帮助你高效地更新项目版本号、检查依赖更新、…...
影墨·今颜模型API接口开发与调用全指南
影墨今颜模型API接口开发与调用全指南 你是不是已经成功部署了影墨今颜模型,看着它能在本地生成惊艳的图片,心里正盘算着怎么把它变成一个能对外服务的“产品”?比如,让公司的设计团队直接调用,或者集成到自己的应用里…...
避坑指南:MoE训练中AllToAll通信的配置与性能调优(以DeepSpeed为例)
MoE训练实战:AllToAll通信性能调优与DeepSpeed配置避坑指南 当你在500张GPU的集群上启动MoE模型训练时,控制台突然刷出"AllToAll timeout"的红色警告——这不是假设场景,而是去年我们在训练千亿参数模型时真实遭遇的噩梦。AllToAll…...
40 个 AI agent 跑营销,还不是最狠的
过去一年,AI 做营销最常见的用法,还是写文案、出海报、改标题、做几个短视频脚本。大家也都看腻了。 现在,真正的变化开始了。 AI 开始往营销里最难、最费人、但又最影响结果的地方发起来进攻,那就是: 盯数据、跑测…...
Windows内存泄漏排查实战:用VMMap揪出C++程序中的‘内存黑洞’(附Heap快照对比技巧)
Windows内存泄漏排查实战:用VMMap精准定位C程序中的"内存黑洞" 1. 内存泄漏:程序员的隐形噩梦 在C开发领域,内存泄漏堪称最顽固的"慢性病"之一。不同于程序崩溃这类明显故障,内存泄漏往往悄无声息地蚕食系统资…...
Simulink仿真速度太慢?试试用C Mex S函数给模型“提提速”
Simulink性能优化实战:用C Mex S函数突破仿真速度瓶颈 当Simulink模型运行缓慢时,工程师们常常陷入漫长的等待。本文将揭示如何通过C Mex S函数这一利器,将仿真速度提升10倍以上,特别适合处理复杂算法、图像处理和大规模系统仿真等…...
Java Web新手必看:EDUCODER头哥MVC用户登录实战(含JDBC连接避坑指南)
Java Web新手实战:EDUCODER平台MVC用户登录全流程解析 第一次接触Java Web开发时,最让人兴奋的莫过于亲手实现一个完整的用户登录系统。这不仅是对MVC架构的直观理解,更是打通前后端数据流的关键里程碑。在EDUCODER这样的实训平台上ÿ…...
5B00,5B01,5B02,1700,1701,1702,1704,P07清零软件G3800,TS3480 ,TS3380 ,G3000,G1810,TS9020, TS8020,TS3480秒修复
下载地址:链接:https://pan.baidu.com/s/1j7Nwv715wX1JL3qidnGyXA?pwd0000 提取码:0000 常见 佳能打印机 型号: G5080 G6080 G7080 G1810 G2810 G3810 G4810 G1800 G2800 G3800 G4800 G5010 G6010 G7010 G1010 G2010 G3010 G4010 G1000 G2000 G3000 G40…...

