【JavaEE】多线程进阶(一)饿汉模式和懒汉模式
多线程进阶(一)
文章目录
- 多线程进阶(一)
- 单例模式
- 饿汉模式
- 懒汉模式
本篇主要引入多线程进阶的单例模式,为后面的大冰山做铺垫
代码案例介绍
单例模式
非常经典的设计模式
啥是设计模式
设计模式好比象棋中的 “棋谱”. 红方当头炮, 黑方马来跳. 针对红方的一些走法, 黑方应招的时候有一些固定的套路. 按照套路来走局势就不会吃亏.
软件开发中也有很多常见的 “问题场景”. 针对这些问题场景, 大佬们总结出了一些固定的套路. 按照这个套路来实现代码, 也不会吃亏.
单例 -> 单个实例(对象)
在有些场景下,希望有的类,只能有一个对象,不能有多个!在这样的场景下就可以使用单例模式了。
举个有意思的例子就是,你只能娶一个老婆,不过你可以生很多娃🥵🥵🥵,娃就不一定是单例的
在代码中,有很多用于管理数据的对象,就应该是”单例“的,例如
mysql JDBC DataSource(描述mysql服务器的位置)
那么这里有个问题:
单例这个事情,还需要设计模式吗?
当我们写代码的时候,只给这个类
new一次对象,不去new多次不就行了?
实际上,设计模式是非常必要的,这其实上是属于设计模式,这完全就是取决于程序员的编程素养。
不过俗话说,宁可相信世界上有鬼,也不能相信人的这张破嘴!人是非常不靠谱的。
这样的思想方法在很多地方都会涉及到:
finalintreface@Overridethrows
于是此时就需要让编译器帮我们做监督,确保这个对象不会出现多个new(出现多个的时候就直接编译报错)
饿汉模式
类加载的同时, 创建实例.
// 饿汉模式
class Singleton{private static Singleton instance = new Singleton();//通过这个方法来获取到刚才的实例//后续如果想使用这个类的实例,都通过 getInstance 方法来获取public static Singleton getInstance(){return instance;}//把构造方法设置为私有,此时类外面的其他代码,就无法 new 出这个类的对象private Singleton(){}
}public class Demo21 {public static void main(String[] args) {//此外又有一个实例,这就不是单例了//Singleton s1 = new Singleton();Singleton s1 = Singleton.getInstance();Singleton s2 = Singleton.getInstance();System.out.println(s1 == s2);//true}
}

懒汉模式
相比于饿汉模式,他就比较从容,在第一次使用的时候,再去创建实例
//懒汉模式class SingletonLazy{private static volatile SingletonLazy instance = null;public static SingletonLazy getInstance(){if (instance == null) {if (instance == null) {instance = new SingletonLazy();}}return instance;}private SingletonLazy(){}
}public class Demo22 {public static void main(String[] args) {//此外又有一个实例,这就不是单例了//Singleton s1 = new Singleton();SingletonLazy s1 = SingletonLazy.getInstance();SingletonLazy s2 = SingletonLazy.getInstance();System.out.println(s1 == s2);//true}
}

我们举个例子:
文本编辑器
记事本
需要打开一个非常大的文件
- 先把所有的内容都加载到内存中,然后再显示内容(加载过程会很慢)
- 只加载一小部分数据到内存,立即显示内容,随着用户翻页,再动态加载其他内容(懒汉模式)
那么这里我们抛出一个问题:
以上两种模式的写法,是否是线程安全的?(如果有多个线程,同时调用
getInstance,是否会出问题?)
如果多个线程,同时修改同一个变量,此时就可能出现线程安全问题
如果多个线程,同时读取同一个变量,这个时候就没什么事情,不会有安全问题
那么我们看看饿汉模式的代码:
public static Singleton getInstance(){return instance;}
饿汉模式下的getInstance只是进行读取,不是修改,那么他也就没有线程安全的问题了~
那我们看看懒汉模式的代码:
if(instance == null){instance = new SingletonLazy();
}
return instance;
它既会读取,又会修改,就可能存在问题~

那么我们怎么保证懒汉模式是线程安全的呢?
类似于下面这种改法吗?
public static SingletonLazy getInstance(){if (instance == null) {synchronized (SingletonLazy.class) {if (instance == null) {instance = new SingletonLazy();}}}return instance;}
当然不是,我们要明确一个事情,就是:锁,不是加了就安全
加的位置对不对,才是关键
- 锁的
{}的范围,是合理的,能够把需要作为整体的每个部分都囊括进去 - 锁的对象,也得是能够起到合理的锁竞争的效果
这样才是真正的加锁
所以修改如下:
public static SingletonLazy getInstance(){synchronized (SingletonLazy.class) {if (instance == null) {if (instance == null) {instance = new SingletonLazy();}}}return instance;}
把if和new合并成一个整体,此时的线程安全就迎刃而解了
不过一旦这么写的话,后续每次调用getInstance,都需要先加锁了
不过这种操作属实是画蛇添足了,加锁是一个开销很大的操作,加锁就可能会涉及到锁冲突 一冲突就会引起阻塞等待。
还有就是:一旦某个代码涉及到 加锁,那么基本上就可以宣告这个代码和“高性能”无缘了~
但是实际上,懒汉模式,线程安全的问题,只是出现在最开始的时候(对象还没开始new呢)
一旦对象new出来了,后续多线程调用getInstance,就只有读操作,就不会线程不安全了~
那么这里抛出一个问题:
是否有什么办法可以让代码线程安全,又不会对执行效率产生太多影响呢?
欲知后事如何,敬请期待下一篇博客~
主要是我临时有事,等明天写完再更😥😥😥😥😥😥😥😥😥

相关文章:
【JavaEE】多线程进阶(一)饿汉模式和懒汉模式
多线程进阶(一) 文章目录 多线程进阶(一)单例模式饿汉模式懒汉模式 本篇主要引入多线程进阶的单例模式,为后面的大冰山做铺垫 代码案例介绍 单例模式 非常经典的设计模式 啥是设计模式 设计模式好比象棋中的 “棋谱”…...
C++树详解
树 树的定义 树(Tree)是n(n≥0)个结点的有限集。n0时称为空树。在任意一颗非空树中:①有且仅有一个特定的称为根(Root)的结点;②当n>1时,其余结点可分为m(…...
支付环境安全漏洞介绍
1、平台支付逻辑全流程分析 2、平台支付漏洞如何利用?买东西还送钱? 3、BURP抓包分析修改支付金额,伪造交易状态? 4、修改购物车参数实现底价购买商品 5、SRC、CTF、HW项目月入10W副业之路 6、如何构建最适合自己的网安学习路线 1…...
抄写Linux源码(Day16:内存管理)
回忆我们需要做的事情: 为了支持 shell 程序的执行,我们需要提供: 1.缺页中断(不理解为什么要这个东西,只是闪客说需要,后边再说) 2.硬盘驱动、文件系统 (shell程序一开始是存放在磁盘里的,所以需要这两个东…...
Cookie和Session详解以及结合生成登录效果
目录 引言 1.Cookie中的数据从哪来数据长啥样? 2.Cookie有什么作用? 3.cookie与session的工作关联? 4.Cookie到哪去? 5.Cookie如何存? 6.Session 7.Cookie与Session的关联与区别 8.通过代码理解 8.1 相关代码 8.2…...
Spring基础以及核心概念(IoC和DIQ)
1.Spring是什么 Spring是包含了众多工具方法的IoC容器 2.loC(Inversion of Control )是什么 IoC:控制反转,Spring是一个控制反转容器(控制反转对象的生命周期) Spring是一个loC容器,我们之前学过的List/Map就是数据存储的容器,to…...
《C和指针》笔记32:多维数组初始化
文章目录 使用括号进行初始化初始化省略维度 使用括号进行初始化 我们可以给数组赋值一个长长的列表: int matrix[2][3] { 100, 101, 102, 110, 111, 112 };它等价于 matrix[0][0]100; matrix[0][1]101; matrix[0][2]102; matrix[1][0]110; matrix[1][1]111; ma…...
零食食品经营小程序商城的作用是什么
零食几乎可以涵盖每个年龄阶段,同时又是市场中常见的零售批发商品,在多个场景中都有销售/购买属性,对消费者来说,购买零食的渠道多种多样,无论线下还是线上,都可随心而购。 庞大市场升级促进下,…...
Java泛型--什么是泛型?
https://www.bilibili.com/video/BV1xJ411n77R?p5&vd_sourcebb1fced25254581cf052adea5e87a1ff 1.泛型类、接口 1.1.泛型类 泛型类的定义 class 类名称 <泛型标识, 泛型标识, ...> {private 泛型标识 变量名;...... }常用的泛型标识:T、E、K、V jav…...
LabVIEW工业虚拟仪器的标准化实施
LabVIEW工业虚拟仪器的标准化实施 创建计算机化的测试和测量系统,从计算机桌面控制外部测量硬件设备,以及在计算机屏幕上显示的类似仪器的面板上查看来自外部设备的测试或测量数据,所有这些都需要虚拟仪器系统软件。该软件允许用户执行所有这…...
JavaScript系列从入门到精通系列第十七篇:JavaScript中的全局作用域
文章目录 前言 1:什么叫作用域 一:全局作用域 1:全局变量的声明 2:变量声明和使用的顺序 3:方法声明和使用的顺序 前言 1:什么叫作用域 可以起作用的范围 function fun(){var a 1; } fun();consol…...
汇编指令集合
...
TinyWebServer整体流程
从main主函数开始: 一、定义MySQL数据库的账号、密码和用到的数据库名称。 二、调用Config获得服务器初始化属性 在这一步确定触发模式端口等信息。 三、创建服务器实例对象 设置根目录、开辟存放http连接对象的空间,开辟定时器空间。 四、利用Confi…...
【Java项目推荐之黑马头条】自媒体文章实现异步上下架(使用Kafka中间件实现)
自媒体文章上下架功能完成 需求分析 流程说明 接口定义 说明接口路径/api/v1/news/down_or_up请求方式POST参数DTO响应结果ResponseResult DTO Data public class WmNewsDto {private Integer id;/*** 是否上架 0 下架 1 上架*/private Short enable;}ResponseResult 自媒…...
自学(黑客)技术方法————网络安全
如果你想自学网络安全,首先你必须了解什么是网络安全!,什么是黑客!! 1.无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面性,例如 Web 安全技术,既有 Web 渗透2.也有 Web 防…...
python+playwright 学习-84 Response 接口返回对象
Response 是获取接口响应对象,根据Response 对象可以获取响应的状态码,响应头部,响应正文等内容。 Response 相关操作方法 all_headers 所有响应HTTP标头, 返回Dict 类型 response.all_headers()body 获取 bytes 类型body内容 response.body()json 返回响应主体的 JS…...
GCN详解
a ⃗ \vec{a} a 向量 a ‾ \overline{a} a 平均值 a ‾ \underline{a} a下横线 a ^ \widehat{a} a (线性回归,直线方程) y尖 a ~ \widetilde{a} a a ˙ \dot{a} a˙ 一阶导数 a \ddot{a} a 二阶导数 H(l)表示l层的节点的特征 W(l)表示l层的参数 D ~ \widet…...
总结二:linux面经
文章目录 1、 Linux中查看进程运行状态的指令、查看内存使用情况的指令、tar解压文件的参数。2、文件权限怎么修改?3、说说常用的Linux命令?4、说说如何以root权限运行某个程序?5、 说说软链接和硬链接的区别?6、说说静态库和动态…...
12、【Qlib】【主要组件】Qlib Recorder:实验管理
11、【Qlib】【主要组件】Qlib Recorder:实验管理 简介Qlib RecorderExperiment ManagerExperimentRecorderRecord Template简介 Qlib包含一个名为QlibRecorder的实验管理系统,旨在帮助用户以高效的方式处理实验并分析结果。 该系统有三个组件: 实验管理器(ExperimentMan…...
三一充填泵:煤矿矸石无害化充填,煤炭绿色高效开采的破局利器
富煤贫油少气是我国的能源禀赋特征,决定了我国以煤炭为主的能源结构,煤炭为国民经济发展提供了重要的基础。煤炭开采过程会对土地、地下水、空气等环境造成较大的污染,但大宗固废煤矸石无害化充填的技术手段可以有效改善这样的情况࿰…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
