【多线程案例】单例模式(懒汉模式和饿汉模式)
文章目录
- 1. 什么是单例模式?
- 2. 立即加载/“饿汉模式”
- 3. 延时加载/“懒汉模式”
- 3.1 第一版
- 3.2 第二版
- 3.3 第三版
- 3.4 第四版
1. 什么是单例模式?
提起单例模式,就必须介绍设计模式,而设计模式就是在软件设计中,针对特殊问题提出的解决方案。它是多年来针对一些常见的问题的解决方法,具有良好的可复用性、可扩展性和可维护性。
标准的设计模式有23种,单例模式就是最常见的一种,其目的是确认一个类只有一个实例对象,并且可以提供一个全局访问点来访问该实例。
单例就是指一个类的实例只有一个,即该类的所有对象都指向用同一个实例。
而多数单例模式并没有结合多线程,在多线程环境下运行有时会出现线程安全问题,所以下面不仅介绍如何实现单例模式,还有单例模式结合多线程使用时的相关知识。
2. 立即加载/“饿汉模式”
立即加载一般还被称作饿汉模式,根据立即,饿汉可以看出十分的急,所以在饿汉模式中,这样单例中的唯一实例对象就被创建。
创建MyObject.java代码如下:
//单例模式、饿汉模式
public class MyObject {//进行封装,防止创建新的对象private static MyObject object = new MyObject();private MyObject(){};//通过这个方法获得对象public static MyObject getObject(){return object;}
}
创建线程类MyThread.java:
public class MyThread extends Thread{@Overridepublic void run() {System.out.println(MyObject.getObject().hashCode());}
}
创建运行类Run.java:
public class Run {//测试单例模式对象是同一个public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.start();t2.start();t3.start();}
}
运行结果:
运行结果相同,说明对象是同一个,成功实现了立即加载型单例设计模式。
3. 延时加载/“懒汉模式”
延时,懒汉可以看出代码并不着急,所以懒汉模式型单例模式中的对象并不像饿汉模式中没有调用前就创建完成,而是在第一调用方法实例时才被创建。
对比饿汉模式:
优点:会减少内存资源浪费。
缺点:多线程环境并发运行,可能会出现线程安全。
3.1 第一版
创建类MyObjectLazy.java,代码如下:
public class MyObjectLazy {//单例模式、懒汉模式private static MyObjectLazy myObjectLazy = null;private static Object lock = new Object();private MyObjectLazy(){};public static MyObjectLazy getMyObjectLazy(){if(myObjectLazy != null){return myObjectLazy;}else{myObjectLazy = new MyObjectLazy();}return myObjectLazy;}}
创建线程类MyThreadLazy.java:
public class MyThreadLazy extends Thread{@Overridepublic void run() {System.out.println(MyObjectLazy.getMyObjectLazy().hashCode());}
}
创建运行类RunLazy.java:
public class RunLazy {//测试对象是不是同一个,是的话就是安全的单例模式public static void main(String[] args) {MyThreadLazy t1 = new MyThreadLazy();MyThreadLazy t2 = new MyThreadLazy();MyThreadLazy t3 = new MyThreadLazy();t1.start();t2.start();t3.start();}
}
运行结果:
结果不同,所以并不是单例模式,其中有问题,造成线程不安全。
3.2 第二版
第一版生成不同对象,所以造成非线程安全,我们可以做出一点修改,对代码加上锁。
修改后的MyObjectLazy.java:
public static MyObjectLazy getMyObjectLazy(){synchronized (lock){if(myObjectLazy == null){myObjectLazy = new MyObjectLazy();}}return myObjectLazy;}
运行结果:
说明这个单例模式是正确实现了。
3.3 第三版
但是第二版又暴露一个问题,上面加锁后相当于整个方法都加锁,上面一个线程没有释放锁,下一个线程将无法运行,造成效率低下。
所以我们继续修改,修改后的MyObjectLazy.java:
public static MyObjectLazy getMyObjectLazy(){try{if(myObjectLazy == null){Thread.sleep(1000);synchronized (lock){myObjectLazy = new MyObjectLazy();}}}catch(InterruptedException e){e.printStackTrace();}return myObjectLazy;}
运行结果:
运行结果又不同了,创建出了三个对象,为什么?这是因为虽然上了锁,但是if已经判断,只是new对象时串行。
虽然效率提高了,但这并不是单例模式。
3.4 第四版
我们可以使用DCL双检查锁机制来实现,进行两次if判断,使线程安全。
修改后MyObjectLazy.java:
//再一次修改代码,加锁只加一块,并且应用DCL双检查机制来实现多线程环境下的延时加载单例模式,保证线程安全public static MyObjectLazy getMyObjectLazy(){try{if(myObjectLazy == null){Thread.sleep(1000);synchronized (lock){if(myObjectLazy == null) {myObjectLazy = new MyObjectLazy();}}}}catch(InterruptedException e){e.printStackTrace();}return myObjectLazy;}
运行结果:
使用双检查锁功能,成功解决了懒汉模式遇到多线程的问题。DCL经常出现在此场景下,我们要学会应用。
相关文章:

【多线程案例】单例模式(懒汉模式和饿汉模式)
文章目录 1. 什么是单例模式?2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式? 提起单例模式,就必须介绍设计模式,而设计模式就是在软件设计中,针对特殊…...

Anaconda - 操作系统安装程序 简要介绍
Anaconda 简要介绍 1. Anaconda 简介2. Anaconda 体系结构3. Anaconda 开发模型4. Anaconda 启动概述5. Anaconda 源码1. 接口2. 自定义组件3. 硬盘分区:使用python-blivet包4. Bootloader5. 各个步骤的配置:6. 安装软件包:7. 安装控制&#…...
【数据库设计】向量搜索HNSW算法优化
做向量存储的过程中,遇到向量搜索的情况处理,HNSW算法是目前向量搜索的主要算法之一,采用的是图算法,主要的问题是使用内存大,训练时间长。做算法优化过程中获得部分技巧,分享出来。 一、算法本身的优化 对…...

多通道振弦数据记录仪应用桥梁安全监测的关键要点
多通道振弦数据记录仪应用桥梁安全监测的关键要点 随着近年来桥梁建设和维护的不断推进,桥梁安全监测越来越成为公共关注的焦点。多通道振弦数据记录仪因其高效、准确的数据采集和处理能力,已经成为桥梁安全监测中不可或缺的设备。本文将从以下几个方面…...

深入了解HTTP代理的工作原理
HTTP代理是一种常见的网络代理方式,它可以帮助用户隐藏自己的IP地址,保护个人隐私和安全。了解HTTP代理的工作原理对于使用HTTP代理的用户来说非常重要。本文将深入介绍HTTP代理的工作原理。 代理服务器的作用 HTTP代理的工作原理基于代理服务器的作用。…...
2023年高教社杯数学建模国赛选题人数+C题进阶版修改思路详解
C题思路 修改版 C题保奖 数据预处理 3σ原则 区间判断法、人为判定 问题 1 聚类分析进行简单的分类 相互关系 数据服从正态分布(K-S检验等判定分布类型后) 才能做person相关性 图表结合(热力图、数据结果表) 分布规律 宏…...

第三章微服务配置中心
文章目录 Nacos配置中心统一配置管理在nacos中添加配置文件从微服务拉取配置 配置热更新多环境共享配置 搭建Nacos集群搭建集群初始化数据库配置Nacos启动nginx反向代理 Nacos配置中心 Nacos配置管理 Nacos除了可以做注册中心,同样可以做配置管理来使用。 统一配置…...

箭头函数(arrow function)与普通函数之间的区别是什么?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 语法简洁性:⭐ this 的绑定:⭐ 不能用作构造函数:⭐ 没有 arguments 对象:⭐ 不适用于方法:⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上…...

JMeter 4.0 如何获取cookie
文章目录 前言JMeter 4.0 如何获取cookie1. 修改jmeter.properties 文件2. 添加HTTP Cookie 管理器3. 获取cookie信息 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。 而且听说点赞的人每天…...

【数字IC/FPGA】Verilog中的force和release
在Verilog中,将force用于variable会覆盖掉过程赋值,或者assign引导的连续(procedural assign)赋值,直到release。 下面通过一个简单的例子展示其用法: 加法器代码 module adder ( input logic [31:0] a, …...

进阶C语言-指针的进阶(上)
指针的进阶 📖1.字符指针📖2.指针数组📖3.数组指针🎈3.1 数组指针的定义🎈3.2 &数组名VS数组名🎈3.3 数组指针的使用 📖4.数组参数、指针参数🎈4.1一维数组传参🎈4.2…...

初始化一个 vite + vue 项目
创建项目 首先使用以下命令创建一个vite项目 npm create vite然后根据提示命令 cd 到刚创建的项目目录下,使用npm install安装所需要的依赖包,再使用npm run dev即可启动项目 配置 vite.config.js 添加process.env配置,如果下面 vue-route…...
关于B+树
在数据库管理系统中,使用b树作为索引的数据结构,相比于B树和二叉树,有以下几个好处: b树的非叶子节点只存储关键字和指针,不存储数据,这样可以增加每个节点的关键字数量,降低树的高度ÿ…...
axios 请求和响应拦截器
1. 创建实例 使用 axios.create() 使用自定义配置创建一个 axios 实例。 const $http axios.create({timeout: 1000,headers: {Content-Type: application/json,} })2. 拦截器 在请求或响应被 then 或者 catch 处理前拦截他们,拦截分为请求拦截和响应拦截。 //…...
Element-ui select远程搜索
template部分: <el-form-item label"用户" prop"userId"><el-selectv-model"temp.userId"placeholder"用户"filterableremote:reserve-keyword"false":remote-method"remoteMethod":loading"loadi…...
【Express.js】Docker部署
Docker部署 本节我们来介绍如何使用 Docker 部署 express 应用 准备工作 linux 系统安装好 Docker一个基础的 evp-express-cli 项目,选上 pkg 工具包Docker 的详细用法本文不做介绍,请先自行查阅了解 在 Docker 中部署源码 一个很简单的部署方法就是…...

面试2:通用能力
15丨如何做好开场:给自我介绍加“特效 第一层,满足面试官对信息的期待 这是对自我介绍的基本要求,把个人信息、主要经历、经验和技能有条理地组织起来, 有逻辑地讲出来。需要找出多段经历的关联性和发展变化,形成连…...

zookeeper/HA集群配置
1.zookeep配置 1.1 安装4台虚拟机 (1)按照如下设置准备四台虚拟机,其中三台作为zookeeper,配置每台机器相应的IP,hostname,下载vim,ntpdate配置定时器定时更新时间,psmiscÿ…...

4.6版本Wordpress漏洞复现
文章目录 一、搭建环境二、漏洞复现1.抓包2.准备payload3.发送payload4.检查是否上传成功5.连接payload 国外的:Wordpress,Drupal,Joomla,这是国外最流行的3大CMS。国内则是DedeCMS和帝国,PHPCMS等。 国内的CMS会追求大…...

腾讯云学生专属便宜云服务器如何购买?
随着云计算技术的快速发展,越来越多的学生开始关注和使用云服务器。腾讯云作为国内知名的云计算服务提供商,推出了一系列针对学生的优惠活动,让更多学生能够享受到云服务器的便利和优势。本文将详细介绍如何购买腾讯云学生专属的便宜云服务器…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...