解决多线程环境下单例模式同时访问生成多个实例
如何满足单例:1.构造方法是private、static方法、if语句判断
①、单线程
Single类
//Single类,定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {System.out.println("创建一次");}public static LazySingleton GetInstance() {//当多线程来临的时候判断是否为null,此时instance就是临界资源,会实例化多个if (instance == null) {instance = new LazySingleton();}return instance;}
}
//客户端代码
public class Main {public static void main(String[] args) {LazySingleton s1= LazySingleton.GetInstance();LazySingleton s2= LazySingleton.GetInstance();if(s1==s2){System.out.println("两个对象是相同的实例");}}
}
运行结果:

这样的话就满足了单例的效果,保证只实例化一个类,因为LazySingleton封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。客户端通过那唯一可以访问的GetInstance方法来访问那一个实例。但如果是多个线程同时调用GetInstance方法,同时运行到了GetInstance方法这儿,它们都会去判断有没有被实例化,判断都为True,那样的话就创建了两个实例,就违背了单例模式,不是一个单例。看下多线程下的单例:
②、多线程
单例类
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {System.out.println("创建一次");}public static LazySingleton GetInstance() {//当多线程来临的时候判断是否为null,此时instance就是临界资源,会实例化多个if (instance == null) {instance = new LazySingleton();}return instance;}
}
main函数
public class Main {public static void main(String[] args) {Runnable r=()->{LazySingleton s1= LazySingleton.GetInstance();LazySingleton s2= LazySingleton.GetInstance();if(s1==s2){System.out.println("两个对象是相同的实例");}};//两个线程Thread t1= new Thread(r);Thread t2= new Thread(r);t1.start();t2.start();}
}
运行结果:

我们会发现对象被创建了两次,我们通过调试发现s1和s2两个对象的地址实际上是不一样的:

当线程t1刚执行完if (instance == null)判断之后时间片到了,t2线程执行完if (instance == null)判断之后就进入方法体生成了实例,此时t1线程又获得了时间片,t1会接着上次中断的地方继续执行,t1线程便会进入方法体又生成了一个新的实例,此时t1和t2线程各生成了一个实例
如何解决这样一个问题呢?
添加锁,当线程位于临界区的时候就上锁,其他线程来临的时候只能在外排队等待。
③、多线程单例——单锁
单例类
package com.example;public class LazySingleton {private static LazySingleton instance;private LazySingleton() {System.out.println("创建一次");}public static LazySingleton GetInstance() {//当多线程来临的时候判断是否为null,此时instance就是临界资源,会实例化多个//方法:加锁-把判断的这部分逻辑上锁synchronized ("") {if (instance == null) {instance = new LazySingleton();}}return instance;}}
main函数
public class Main {public static void main(String[] args) {Runnable r=()->{LazySingleton s1= LazySingleton.GetInstance();LazySingleton s2= LazySingleton.GetInstance();if(s1==s2){System.out.println("两个对象是相同的实例");}};//两个线程Thread t1= new Thread(r);Thread t2= new Thread(r);t1.start();t2.start();}
}
运行结果:

发现对象创建了一次。在同一时刻加了锁的那部分程序只有一个线程可以进入,我们可以让最先进入的那个线程先上一把锁,创建实例。后面在进入的线程就不会再去创建对象实例了,因为第一名来的线程已经创建了,你这个判断的结果是False,自然无法创建了。这样的话就保证了多个线程同时访问的话不会有多个实例化。解决了上面单实例带来的问题。但每次进入的线程都需要先加锁在判断,我都还不知道有没有创建过这个实例呢你就让我加锁,第一名已经实例化过了,我进去再加锁,在判断一次,如果有上百个线程同时访问呢,这样的工作重复上百次,不是很影响我这个程序的性能吗?我们就可以用到双重锁定来解决这个问题
④、多线程——双重锁(Double-Check Locking)
package com.example;public class DoubleLockSingleton {private static DoubleLockSingleton instance;private DoubleLockSingleton() {System.out.println("实例化了一次");}public static DoubleLockSingleton GetInstance() {//第一层判断:先判断实例是否存在,不存在再加锁处理if (instance == null) {synchronized ("") {//第二层判断if (instance == null) {instance = new DoubleLockSingleton();}}}return instance;}
}
通过这样两重的判断,进入的线程不用每次都加锁,只是在实例未被创建的时候在加锁处理。同时也保证多线程的安全。
相关文章:
解决多线程环境下单例模式同时访问生成多个实例
如何满足单例:1.构造方法是private、static方法、if语句判断 ①、单线程 Single类 //Single类,定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例 public class LazySi…...
转转闲鱼交易猫源码搭建
后台一键生成链接,独立后台管理 教程:修改数据库config/Conn.php 不会可以看源码里有教程 下载程序:https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3...
设计模式精华版汇总
以下是个人整理的设计模式汇总,将会持续更新工作和面试中经常用到的设计模式。 设计模式-装饰者模式(包装模式)- 案例分析和源码分析 设计模式-代理模式:控制访问的设计模式 - 案例分析 设计模式-门面模式…...
uniapp实现带参数二维码
view <view class"canvas"><!-- 二维码插件 width height设置宽高 --><canvas canvas-id"qrcode" :style"{width: ${qrcodeSize}px, height: ${qrcodeSize}px}" /></view> script import uQRCode from /utils/uqrcod…...
金融行业软件测试面试题及其答案
下面是一些常见的金融行业软件测试面试题及其答案: 1. 什么是金融行业软件测试? 金融行业软件测试是针对金融领域的软件系统进行验证和确认的过程,旨在确保软件在安全、稳定、可靠和符合法规要求的条件下运行。 2. 解释一下金融软件中的风险…...
强化学习QLearning 进行迷宫游戏和代码
强化学习是机器学习里面的一个分支。它强调基于环境而探索行动、学习,以取得最大化的预期收益。其灵感来源于心理学中的行为主义理论,既有机体如何在环境给予的奖励或者惩罚的刺激下,逐步形成对刺激的预期,产生能够最大利益的习惯…...
Vue2 第九节 过滤器
(1)定义:对要显示的数据进行特定格式化后再显示 (2)语法: ① 注册过滤器 1)Vue.filter(name, callback) 全局过滤器 2) new Vue({filters:{}}) 局部过滤器 ② 使用过滤器 1&…...
Swift 对象数组去重
使用 reduce 方法去重 使用 reduce 方法结合 contains 方法可以实现去重。reduce 方法用于将数组的元素进行累积计算,而 contains 方法用于检查元素是否已经存在于结果数组中。 struct SearchRecord: Equatable {let id: Intlet name: String }let records [Sear…...
代码随想录算法训练营day52 300.递增子序列 674.最长连续递增子序列 718.最长重复子数组
题目链接300.递增子序列 class Solution {public int lengthOfLIS(int[] nums) {int[] dp new int[nums.length];Arrays.fill(dp, 1);for(int i 0; i < nums.length; i){for(int j 0; j < i; j){if(nums[i] > nums[j]){dp[i] Math.max(dp[i], dp[j] 1);}}}int r…...
Android 面试题 虚拟机、进程、线程 七
🔥 安卓虚拟机 🔥 虽然Android程序是使用Java语言开发的,当然,现在也可以使用kotlin语言。但是实际上我们开发出来的Android程序并不能运行在JVM上,而是只能运行在一个类似JVM的Android虚拟机上。Android虚拟机有两种&…...
Flutter 状态组件 InheritedWidget
Flutter 状态组件 InheritedWidget 视频 前言 今天会讲下 inheritedWidget 组件,InheritedWidget 是 Flutter 中非常重要和强大的一种 Widget,它可以使 Widget 树中的祖先 Widget 共享数据给它们的后代 Widget,从而简化了状态管理和数据传递…...
<C++> 入门
在学习完C语言的基础上,继续开始C的学习。 C是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。熟悉C语言之后,对C学习有一定的帮助。 1. 补充C语言语法的不足,以及C是如…...
政策加持智能家居市场,涂鸦赋能客户打造“以人为本”智能生活新方式
7月18日,商务部等13部门联合发布了《关于促进家居消费若干措施的通知》(以下简称《通知》),《通知》指出,创新培育智能消费,支持企业运用物联网、云计算、人工智能等技术,着重加快智能家电、智能…...
安全渗透初级知识总结-2
CIA三原则:保密性,完整性,可用性 https:解决了安全传输问题 核心技术:用非对称加密传输对称加密的秘钥,然后用对称秘钥通信 抓包:Wireshark、tshark、tcpdump valueof方法是一个所有对象都拥有的方法&am…...
数学建模的32种常规方法及案例代码
比赛期间整理的数学建模的32种常规方法及案例代码友情分享: 链接:https://pan.baidu.com/s/18uDr1113a0jhd2No8O1Nog 提取码:xae5 在数学建模中,常规算法是指那些被广泛应用于各种问题求解的经典算法。这些算法覆盖了不同的数学…...
【Django+Vue】英文成绩管理平台--20230727
能够满足大部分核心需求(标绿):报表部分应该比较难。 项目地址 前端编译 https://gitlab.com/m7840/toeic_vue_dist Vue源码 https://gitlab.com/m7840/toeic_vue Django源码 https://gitlab.com/m7840/toeic_python 项目架构 流程 …...
栈-模拟栈
实现一个栈,栈初始为空,支持四种操作: push x – 向栈顶插入一个数 x; pop – 从栈顶弹出一个数; empty – 判断栈是否为空; query – 查询栈顶元素。 现在要对栈进行 M 个操作,其中的每个…...
图观| 从王宝强、费翔、阿汤哥等新上映的电影聊聊图的智能推荐场景
从技术的视角来看,推荐系统本质上是在用户需求不明确的情况下,从海量的信息中为用户过滤出他可能感兴趣的信息的一种技术手段。 我们日常接触到的智能推荐有: 电商网站:如淘宝、天猫、京东、Amazon…… 生活服务:如美…...
Redis系列一:介绍
介绍 The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker. 相关资源 Redis 官网:https://redis.io/ 源码地址:https://github.com/redis/redis Redis 在线测试&#…...
Java 设计模式 - 单例模式 - 保证类只有一个实例
单例模式 - 保证类只有一个实例 为什么使用单例模式?单例模式的实现方式1. 饿汉式(Eager Initialization)2. 懒汉式(Lazy Initialization)3. 双重检查锁(Double-Checked Locking)4. 静态内部类&…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
