单例模式:饿汉模式、懒汉模式
目录
一、什么是单例模式
二、饿汉模式
三、懒汉模式
一、什么是单例模式
单例模式是Java中的设计模式之一,能够保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例
单例模式有很多实现方式,最常见的是饿汉和懒汉两种模式
二、饿汉模式
饿汉模式在类加载时就创建实例
如何实现饿汉式单例模式?
1. 在类中完成实例的初始化,在创建的类中创建唯一实例
2. 对外提供获取该唯一实例的方法,提供访问该实例的全局静态方法getInstance(),来获取该类的唯一实例
3. 构造方法私有化,保证类外部不能实例化,只有在类中创建的唯一实例
//饿汉式单例模式
public class HungrySingLeton {//在类中创建唯一实例private static final HungrySingLeton instance = new HungrySingLeton();//构造方法私有化,保证类外部不能进行实例化private HungrySingLeton(){}//对外提供获取该唯一实例的方法public static HungrySingLeton getInstance(){return instance;}
}
饿汉式单例模式线程安全吗?
饿汉式单例模式在类加载时就进行初始化,创建唯一实例。它在线程还没出现之前就实例化了,外部只能通过getInstance()方法来获取唯一实例,相当于“读操作”,因此是线程安全的
饿汉式单例模式的缺点
在类加载时就创建实例,并一直在内存中,若不使用该实例,该实例仍然存在,此时存在内存浪费问题
三、懒汉模式
类加载时不创建实例,直到第一次使用的时候才创建实例
如何实现懒汉模式?
懒汉模式的实现与饿汉模式类似,唯一的区别是懒汉模式直到第一次使用的时候才会创建实例
1. 在类中创建唯一实例,并将该实例的初始值设为null
2. 对外提供获取该唯一实例的方法,若是第一次使用该方法,则创建实例
3. 构造方法私有化,保证类外部不能实例化,只有在类中创建的唯一实例
public class LazySingleton {//在类中创建唯一实例,并将其置为nullprivate static LazySingleton instance = null;//构造方法私有化,保证类外部不能进行实例化private LazySingleton(){}//对外提供获取该唯一实例的方法public static LazySingleton getInstance(){//若是第一次使用该方法,则初始化instanceif (instance == null){instance = new LazySingleton();}return instance;}}
懒汉模式线程安全吗?
在多线程情况下,可能会出现创建多个实例的情况

如何解决线程安全问题?
通过加锁,来解决线程安全问题
将判断instance是否为空,和创建实例两个操作加上锁,或是直接在方法上加上synchronized,从而保证在上图的情况下,也只创建一个实例
public static LazySingleton getInstance(){synchronized (LazySingleton.class){//若是第一次使用该方法,则初始化instanceif (instance == null){instance = new LazySingleton();}}return instance;}
或
public synchronized static LazySingleton getInstance(){//若是第一次使用该方法,则初始化instanceif (instance == null){instance = new LazySingleton();}return instance;}
此时

由于加锁和解锁开销较高,而懒汉式单例模式仅在第一次调用时,才会存在可能创建多个实例的问题,在后面调用getInstance()方法时,判断instance不为空,直接返回instance,而在加锁后,无论是否已经存在实例,在多线程情况下都会发生阻塞,此时存在执行效率低的问题
因此,在加锁前,判断是否已经创建实例,若已经创建实例,则直接返回instance,若未创建实例,则进行加锁操作
public static LazySingleton getInstance(){//判断是否已经创建实例,若已经创建实例,则不加锁,直接返回instanceif(instance == null){//若实例未创建,则向下执行来竞争锁//竞争成功的锁,进行创建实例操作synchronized (LazySingleton.class){//在竞争成功的锁创建实例并释放锁后//其他竞争到锁的线程被内层if挡住,不会创建多个实例if (instance == null){instance = new LazySingleton();}}}return instance;}
通过两个if条件判断,降低了锁竞争的频率,既保证了线程安全,又提高了执行效率
此时线程安全了吗?
此时,指令重排序,也可能引起线程安全问题
指令重排序,是编译器优化的一种方式,通过调整原有代码的执行顺序,在保证逻辑不变的前提下,提高程序的效率
在创建实例时,可将其分为三个步骤
1. 申请一段内存空间
2. 在该内存空间上调用构造方法,创建出实例
3. 将该内存地址赋值给instance引用变量
正常情况下,创建实例是按照1 2 3的顺序来执行的,而编译器也可能会将其优化为1 3 2的顺序来执行
而当按照1 3 2 的方式来创建实例时,就可能会出现问题

如何解决指令重排序带来的线程安全问题?
使用volatile
volatile能够禁止指令重排序,从而保证创建实例时,按照1 2 3的顺序来创建出实例,保证创建出初始化的实例
public class LazySingleton {//在类中创建唯一实例,并将其置为null//volatile:禁止指令重排序private volatile static LazySingleton instance = null;//构造方法私有化,保证类外部不能进行实例化private LazySingleton() {}//对外提供获取该唯一实例的方法public static LazySingleton getInstance() {//判断是否已经创建实例,若已经创建实例,则不加锁,直接返回instanceif (instance == null) {//若实例未创建,则向下执行来竞争锁//竞争成功的锁,进行创建实例操作synchronized (LazySingleton.class) {//在竞争成功的锁创建实例并释放锁后//其他竞争到锁的线程被内层if挡住,不会创建多个实例if (instance == null) {instance = new LazySingleton();}}}return instance;}
}
懒汉模式在类加载时,并没有进行实例化,而是在第一次调用getInstance()方法的时候,才进行实例化。若一直没有调用getInstance()方法,则不创建该唯一实例,此时节省了实例化的开销
相关文章:
单例模式:饿汉模式、懒汉模式
目录 一、什么是单例模式 二、饿汉模式 三、懒汉模式 一、什么是单例模式 单例模式是Java中的设计模式之一,能够保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例 单例模式有很多实现方式,最常见的是饿汉和懒汉两种模式 二、…...
提升方法AdaBoost
通过改变训练样本的权重学习多个分类器,并将这些线性分类器进行线性组合,提高分类性能。 AdaBoost 提高前一轮被分类错误的权值,降低前一轮被分类正确的权值;加大分类误差错误率小的弱分类器权重。 算法: 输入&…...
Python自动化测试系列[v1.0.0][多种数据驱动实现附源码]
前情提要 请确保已经熟练掌握元素定位的常用方法及基本支持,请参考Python自动化测试系列[v1.0.0][元素定位] 数据驱动测试是自动化测试中一种重要的设计模式,这种设计模式可以将测试数据和测试代码分开,实现数据与代码解耦,与此同…...
【论文笔记】Gemini: A Family of Highly Capable Multimodal Models——细看Gemini
Gemini 【一句话总结,对标GPT4,模型还是transformer的docoder部分,提出三个不同版本的Gemini模型,Ultra的最牛逼,Nano的可以用在手机上。】 谷歌提出了一个新系列多模态模型——Gemini家族模型,包括Ultra…...
iOS加密CoreML模型
生成模型加密密钥 必须在Xcode的Preferences的Accounts页面登录Apple ID,才能在Xcode中生成模型加密密钥。 在Xcode中打开模型,单击Utilities选项卡,然后单击“Create Encryption Key”按钮。 从下拉菜单中选择当前App的Personal Team&…...
Springboot自定义start首发预告
Springboot自定义start首发预告 基于Springboot的自定义start , 减少项目建设重复工作, 如 依赖 , 出入参包装 , 日志打印 , mybatis基本配置等等等. 优点 模块化 可插拔 易于维护和升级 定制化 社区支持(后期支持) 发布时间 预告: 2023-12-10 预计发布: 2024-1-1 , 元旦首…...
[GWCTF 2019]我有一个数据库1
提示 信息收集phpmyadmin的版本漏洞 这里看起来不像是加密应该是编码错误 这里访问robots.txt 直接把phpinfo.php放出来了 这里能看到它所有的信息 这里并没有能找到可控点 用dirsearch扫了一遍 ####注意扫描buuctf的题需要控制扫描速度,每一秒只能扫10个多一个都…...
【LeetCode每日一题】1904. 你完成的完整对局数
给你两个字符串 startTime 和 finishTime ,均符合 "HH:MM" 格式,分别表示你 进入 和 退出 游戏的确切时间,请计算在整个游戏会话期间,你完成的 完整对局的对局数 。 如果 finishTime 早于 startTime ,这表示…...
+0和不+0的性能差异
前几日,有群友转发了某位技术大佬的weibo。并在群里询问如下两个函数哪个执行的速度比较快(weibo内容)。 func g(n int, ch chan<- int) {r : 0for i : 0; i < n; i {r i}ch <- r 0 }func f(n int, ch chan<- int) {r : 0for …...
美颜技术讲解:视频美颜SDK的开发与集成
如今,美颜技术的应用愈发成为吸引用户的一项重要功能。本文将深入探讨视频美颜SDK的开发与集成,揭示其背后的技术原理和实现步骤。 一、美颜技术的背后 美颜技术并非仅仅是简单的滤镜效果,而是一项涉及复杂图像处理和算法的技术。在视频美颜…...
期末数组函数加强练习
前言:由于时间问题,部分题解取自网友,但都是做过的好题。 对于有些用c实现的题目,可以转化成c实现,cin看成c的读入,可以用scanf,输出cout看作printf,endl即换行符 开胃菜ÿ…...
如何下载B站视频?我来教你B站视频下载方法
如何下载B站视频?B站作为一个巨大的宝藏库,日常可以拿它作为娱乐工具,刷一些有趣新奇的短视频。也可以把它作为一款成长学习工具,具有丰富的公开课、纪录片内容。 对于较短的视频来说,花费几分钟时间看一下就结束了&am…...
AcWing 3709:单链表节点交换 ← 四川大学考研机试题
【题目来源】 https://www.acwing.com/problem/content/3712/【题目描述】 输入一个单链表,依次交换前2个数,第3、4个数,第5、6个数,…,以此类推,直到操作完整个链表。 如果链表长度是奇数,则最…...
RocketMQ源码 Broker-ConsumerFilterManager 消费者数据过滤管理组件源码分析
前言 ConsumerFilterManager 继承了ConfigManager配置管理组件,拥有将内存数据持久化到磁盘文件consumerFilter.json的能力。它主要负责,对在消费者拉取消息时,进行消息数据过滤,且只针对使用表达式过滤的消费者有效。 源码版本&…...
数据挖掘-07-航空公司客户价值分析(包括数据和代码)
文章目录 0. 数据代码下载1. 背景与挖掘目标2. 导入相关库,加载数据2.1客户基本信息分布a. 绘制会员性别比例饼图b. 绘制会员各级别人数条形图c. 绘制年龄分布图 2.2 客户乘机信息分布分析a. 绘制客户飞行次数箱线图b. 绘制客户总飞行公里数箱线图 2.3 客户积分信息…...
浏览器 css 默认的字体图表
以下是一些常见的浏览器(PC端)中网站 CSS 默认字体及其对应的字体系列(font family): 浏览器默认字体字体系列(font family)ChromeArial, sans-serif“Arial”, “Helvetica Neue”, Helvetica…...
JAVA:注册表窗口的实现
目录 题目要求: 思路大意: 窗体的实现: 窗口A: 窗口B: 窗体之间的构思: 关键代码的实现: 窗口A: 封装列表: 窗口B: 题目要求: 使用…...
Liunx Centos 防火墙操作
liunx centos 防火墙 查看防火墙状态 systemctl status firewalld查看已经开放的端口 firewall-cmd --list-ports添加端口3306 firewall-cmd --zonepublic --add-port3306/tcp --permanent重启防火墙 firewall-cmd --reload数据库开放账号可以外网登陆 mysql -u root -p …...
VirtualBox 和 Vagrant 快速安装 Centos7 报错
VirtualBox 和 Vagrant 快速安装 Centos7 报错 今天尝试用 VirtualBox 和 Vagrant 快速安装 Centos7,BUG 多多! 1)下载 6.1.26 版本 VirtualBox,Windows11 不兼容???什么鬼? 解决…...
使用Python进行数学四则运算
当我们讨论到Python中的计算问题时,我们必然涉及到加法运算符()、减法运算符(-)、乘法运算符(*)以及除法运算符(/)这四大常见的算术运算。下面,我将为您展示如…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
