当前位置: 首页 > news >正文

Java实现线程安全的单例模式

单例模式:保证某个类在程序中只存在唯⼀⼀份实例,而不会创建出多个实例,单例模式的类一般是构造器私有,通过一个方法返回唯一实例;

点这里查看线程安全的详细讲解;

常见的单例模式分为饿汉式和懒汉式

一、饿汉式

饿汉式会在类加载的时候创建对象并初始化;

public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}

以上是一个饿汉式实现的单例模式的典型代码;由代码可以看出, 在类加载的时候对象已经创建好了,也就是不管你需不需要使用,都已经存在了,由 getInstance 方法返回这个对象,getInstance 方法直接 return,只涉及到读操作,不涉及写操作,因此饿汉式是线程安全的;

二、懒汉式

懒汉式在类加载的时候并不会直接创建出实例,而是在第一次使用的时候才会创建;

public class Singleton {private static Singleton instance = null;private Singleton() { }public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

以上代码是懒汉式实现的单例模式的典型代码;其中, 刚开始的时候,instance 对象并没有实例化,在使用 getInstance 方法获取该对象时,会判断该对象是否为空,为空才会初始化(也就是第一次使用的时候为空),之后使用就会直接返回该对象;但是 getInstance 方法既存在读操作,也存在写操作 instance = new Singleton(); ,那么在多线程的情况下,是否会存在线程安全问题呢?答案是肯定的,试想如果两个线程同时执行到 if 判断,此时 instance 为空,两个线程都会进入 if 语句内,这样两个线程就会各自创建两个对象并返回,这就违背了单例模式的初衷;

那么如何解决这个问题呢?

优化一

可以使用 synchronized 加锁,由于两个线程不应该同时判断出 instance == null,故可以对整个 if 块使用 synchronized 进行加锁;于是代码就变为:

public class Singleton {private static Singleton instance = null;private Singleton() { }public static Singleton getInstance() {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}return instance;}
}

这样一来,在多线程的情况下,当一个线程进入到 if 块内,其他线程就会阻塞等待,等待出了synchronized 块之后,instance 实例也就 new 完了,其他线程再进行判断 instance 就不为 null 了,但是这样一来,之后的每次调用 getInstance 方法都会进行加锁,释放锁等操作,这样系统开销就非常大,影响效率,而我们只需要在第一次创建实例的时候加锁,因此即为了保证线程安全,又要保证效率,就得对上述代码进一步优化;

优化二

由于我们只需要在第一次创建实例的时候才加锁,因此可以在 synchronized 外面再包装一层 if 判断,于是代码进一步变为:

public class Singleton {private static Singleton instance = null;private Singleton() { }public static Singleton getInstance() {if(instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

这样一来,既保证了线程安全,又不会非常影响效率,但是上述代码还存在一个问题:指令重排序问题,在 new Singleton() 实例的时候,new 操作可以被拆分为三步:

1)申请内存空间;

2)在内存空间上构造对象;

3)把内存地址赋值给实例引用;

编译器为了执行效率,会优化这三步的顺序,但是 1 肯定是最先执行的,因此 new 操作可能的执行顺序为 1 -> 2 -> 3,1 -> 3 -> 2,当执行顺序为后者的时候,假设有两个线程 t1,t2,在 t1 执行完 1, 3 还来不及执行 2 的时候,此时 t2 线程执行到 if 判断,此时由于 t1 线程执行了步骤 3 ,所以 t2 判断 if 不为 null,就直接返回 instance 对象了,但此时 instance 指向的是一个还没有初始化的非法对象,因此 t2 线程的后续代码访问 instance 里面的属性和方法时就会出错,为了避免这种情况,需要对上述代码再进行优化;

优化三

使用 volatile 关键字,告诉编译器不要优化指令重排序;

public class Singleton {private static volatile Singleton instance = null;private Singleton() { }public static Singleton getInstance() {if(instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

至此,线程安全的懒汉式就实现了;

 

相关文章:

Java实现线程安全的单例模式

单例模式:保证某个类在程序中只存在唯⼀⼀份实例,而不会创建出多个实例,单例模式的类一般是构造器私有,通过一个方法返回唯一实例; 点这里查看线程安全的详细讲解; 常见的单例模式分为饿汉式和懒汉式 一…...

osg库的下载和安装

下载 下载地址:https://github.com/openscenegraph/OpenSceneGraph 安装 打开Cmake.exe,将上述下载的osg文件下的CMakeLists.txt文件拖入Cmake界面中。 在其路径下新建一个build文件 并配置cmake,点击Configure 修改如下几个选项 ACTUAL_3RDPARTY_DIR BUILD_OSG_EXAM…...

HTML、ASP.NET、XML、Javascript、DIV+CSS、JQuery、AJax的起源与简介

目录 HTML简介: 起源: ASP.NET简介: 起源: XML简介: 起源: JavaScript简介: 起源: DIVCSS简介: 起源: JQuery简介: 起源: AJax简介: HTML简介: HTML(Hyper Text Markup Language,超文本标记语言…...

SpringCloud微服务远程接口调用

一、概念 使用springcloud将项目拆分成一个一个微服务之后,微服务之间的接口调用就需要通过远程的方式实现,这里将介绍springcloud提供的两个微服务组件来介绍如何进行微服务间的远程接口调用。 1、使用RestTEmplate LoadBalanced来实现远程接口调用及…...

MySQL优化器的SQL重写规则

MySQL优化器的SQL重写规则 MySQL优化器的SQL重写规则&#xff1a;MySQL优化器会根据一定的规则对输入的SQL在保证含义不变的情况下进行SQL的优化重写。 1. 条件简化 1.1 移除不必要的括号 例如&#xff1a; ((a 5 AND b c) OR ((a > c) AND (c < 5))); --优化后 (a…...

57.void指针(万能指针)

目录 一.什么是void指针 二.视频教程 一.什么是void指针 在定义变量的时候&#xff0c;需要用到变量的类型&#xff0c;变量的类型在表示在内存中的大小&#xff0c;而void是空&#xff0c;表示的是无类型。所以如果用void来定义一个变量会发生错误&#xff08;无法在内存中挖…...

国科大-智能计算系统(AICS)期末试题(2024春)

国科大-智能计算系统期末试题&#xff08;2024春&#xff09; 填空题简答题最后一道大题 部分题目记录 填空题 卷积层中&#xff0c;input维度为16322020&#xff0c;filter维度为1283233&#xff0c;stride2&#xff0c;pad_left pad_top 0,pad_right pad_bottom 1,outpu…...

训练Pytorch深度学习模型出现StopIteration

训练一个深度学习检测模型&#xff0c;突然出现&#xff1a; 是因为next(batch_iterator)&#xff0c;可能迭代器读出来的数据为空。 # load train data# 原先代码images, targets next(batch_iterator)# 更改为&#xff1a;try:images, targets next(batch_iterator)except…...

windows上安装MongoDB,springboot整合MongoDB

上一篇文章已经通过在Ubuntu上安装MongoDB详细介绍了MongoDB的各种命令用法。 Ubuntu上安装、使用MongoDB详细教程https://blog.csdn.net/heyl163_/article/details/133781878 这篇文章介绍一下在windows上安装MongoDB&#xff0c;并通过在springboot项目中使用MongoDB记录用户…...

python_04

37、列表推导式 # 作用&#xff1a;快速生成列表 # 列表变量名 [x for x in range(开始值&#xff0c;结束值&#xff0c;步长) if 条件] # 注意&#xff1a;左闭右开 list1 [i for i in range(0,100)] print(list1) # list1 [i for i in range(0,100)] # print(list1)list…...

音视频视频点播

视频点播是集音视频采集&#xff0c;编辑&#xff0c;上传&#xff0c;自动化转码处理&#xff0c;媒体资源管理&#xff0c;高效云剪辑处理&#xff0c;分发加速&#xff0c;视频播放于一体的一站式音视频点播解决方案 阿里云视频点播基于阿里云强大的基础设施服务&#xff0c…...

Git常用命令1

1、设置用户签名 ①基本语法&#xff1a; git config --global user.name 用户名 git config --global user.email 邮箱 ②实际操作 ③查询是否设置成功 cat ~/.gitconfig 注&#xff1a;签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交…...

Nextjs使用教程

一.手动创建项目 建议看这个中文网站文档,这个里面的案例配置都是手动的,也可以往下看我这个博客一步步操作 1.在目录下执行下面命令,初始化package.json文件 npm init -y2.安装react相关包以及next包 yarn add next react react-dom // 或者 npm install --save next react…...

mysql的增删查改(进阶)

目录 一. 更复杂的新增 二. 查询 2.1 聚合查询 COUNT SUM AVG MAX MIN 2.1.2 分组查询 group by 子句 2.1.3 HAVING 2.2 联合查询/多表查询 2.2.1 内连接 2.2.2 外连接 2.2.3 全外连接 2.2.4 自连接 2.2.5 子查询 2.2.6 合并查询 一. 更复杂的新增 将从表名查询到…...

九、从0开始卷出一个新项目之瑞萨RZN2L生产烧录固件(jflash擦写读外挂flash)

目录 七、生产烧录固件(jflash擦/写/读外挂flash) 7.1 flash母片读写 7.2 jflash擦/写/读外挂flash 九、从0开始卷出一个新项目之瑞萨RZN2L 七、生产烧录固件(jflash擦写读外挂flash) 七、生产烧录固件(jflash擦/写/读外挂flash) 7.1 flash母片读写 略 7.2 jflash擦/写/读…...

安徽某高校数据挖掘作业4-5 (与一些碎碎念)

1. 编写程序求函数、、的极限。 解答&#xff1a; import sympy as sp# 定义符号变量 x x sp.symbols(x)# 定义函数 f1 sp.sin(20 * x) / x f2 (1 4 * x)**(2 / x) f3 (1 4 / x)**(2 * x)# 计算极限 limit1 sp.limit(f1, x, 0) limit2 sp.limit(f2, x, 0) limit3 sp…...

基于ES安装IK分词插件

前言 IK分词器插件是为Elasticsearch设计的中文分词插件&#xff0c;由Elasticsearch的官方团队之外的开发者medcl开发。它主要针对中文文本的分词需求&#xff0c;提供了较为准确的中文分词能力。以下是IK分词器插件的一些特点&#xff1a; 智能分词&#xff1a;IK分词器采用基…...

php项目加密源码

软件简介 压缩包里有多少个php就会被加密多少个PHP、php无需安装任何插件。源码全开源 如果上传的压缩包里有子文件夹&#xff08;子文件夹里的php文件也会被加密&#xff09;&#xff0c;加密后的压缩包需要先修复一下&#xff0c;步骤&#xff1a;打开压缩包 》 工具 》 修…...

测绘GIS和遥感领域比较好的公众号有哪些

测绘GIS和遥感领域&#xff0c;微信公众号作为信息传播和知识分享的重要渠道&#xff0c;为从业者提供了一个快速获取行业动态、技术进展和职业发展机会的平台。分享一些在测绘GIS和遥感领域表现突出的公众号推荐&#xff1a; 1. 慧天地&#xff1a;慧天地是一个知名的测绘公众…...

【技术实操】银河高级服务器操作系统实例分享,达梦数据库服务器 oom 问题分析

1. 服务器环境以及配置 【 机型】 处理器&#xff1a; HUAWEIKunpeng 920 5220 内存&#xff1a; 400518528 kB 主板型号&#xff1a; Chaoqiang K620 series 整机类型/架构&#xff1a; ARM BIOS 版本&#xff1a; KL4.41.028.TF.220224.R 固件版本&#xff1a; KL4.41…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...