多线程系列五:面试中常考的单例模式
1.设计模式
在了解单例模式之前我们先要了解设计模式:
设计模式是一种软性规定,遵守了设计模式,代码的下限就被兜住了,类似于棋谱,是大佬设计出来的,让小白程序员也能写出好的代码
设计模式有很多种,不同语言中也有不同的设计模式,设计模式可认为是对编程语言语法的补充
2.单例模式
单例=单个实例(对象),某个类在一个进程中,只应创建出一个实例,原则上不应该有多个,使用单例模式,就可以对代码进行一个更严格的校验和检查,有的代码中,需要使用一个对象来管理/持有大量的数据,此时有一个对象即可,比如一个对象管理10G数据,如果不小心创建了多个对象,内存空间就会成倍增长,机器就顶不住了
唯一对象如何保证呢?
1️⃣:可通过君子约定,写一个文档约定每个接手维护代码的程序员都不能把这个类创建多个实例,但是并不靠谱
2️⃣:希望让机器对代码中指定的类,创建的实例个数进行校验,如果发现创建多个实例了,就直接对编译报错,如果能做到这一点,就可以放心的写代码
**Java语法本身没有直接约定某个对象创建几个实例,就要用一些奇淫巧技来实现,单例模式具体的实现方式有很多,最常见的就是“饿汉模式”和“懒汉模式”两种
2.1饿汉模式
我们先看一下整体代码,接下来我们一一解释
class Singleton{private static Singleton instance = new Singleton();private Singleton(){}public static Singleton getInstance(){return instance;}
}
这个引用就是希望创建的唯一实例的引用
instance
是Singleton类对象里持有的属性,在Java中每个类的类对象只存在一个,类对象static属性自然也只有一个,因此instance指向的这个对象就是唯一的一个对象
其他代码没法new,从根本上让其他人想new也new不了,只能用getInstance
后续其它代码若想使用这个类的实例,就要通过
getInstance()
这个方法来进行获取,不应该在其它代码中重新new这个对象,而是使用这个方法获取到现成的对象
在main中的使用
对于饿汉模式,getInstance直接返回Instance实例,这个操作本质上是读操作,多个线程读取同一个变量,是线程安全的
2.2懒汉模式单线程版
在懒汉模式中,类加载的时候不创建实例,第一次使用的时候才创建实例,在懒汉模式中,代码有读也有写,是线程不安全的
我们先来看一下单线程版的代码,如果首次调用getInstance,那么此时Instance引用为null,就会进入if条件,从而把实例创建出来,如果后续再使用getInstance,由于Instance已经不再是null了,此时就不会进入if,直接返回之前创建好的引用了,这样设定仍可保证该类的实例是唯一一个,与此同时,创建的实例的时机就不是程序启动时了,而是第一次调用getInstance时,这个操作执行时机就不知道了,就看你的实际需求,大概率要比饿汉模式这种方式晚一些,甚至有可能整个程序压根用不到这个方法,也就把创建的操作省下了
class SingletonLazy{private static SingletonLazy instance = null;private SingletonLazy(){}public static SingletonLazy getInstance(){if (instance ==null){instance = new SingletonLazy();}return instance;}
}
会造成创建出两个实例的问题
如果单个线程使用这个代码是安全的,但是在多线程情况下,由于线程是抢占式执行,不确定执行的实际,就会创建出多个实例
加上synchronized可以改善这里的线程问题
class SingletonLazy{private static SingletonLazy instance = null;private SingletonLazy(){}public synchronized static SingletonLazy getInstance(){if (instance ==null){instance = new SingletonLazy();}return instance;}
}
但是Instance已经创建过了,此时后续再调用getInstance就都是直接返回Instance实例了,此时操作就是纯粹的读操作了,也就不会有线程安全问题了,这时仍然是每次调用都先加锁再解锁,效率就非常低了
接下来我们看看如何改进
2.3懒汉模式多线程版(这是个重点的面试题,主要是考虑为什么要加东西,每个地方解决什么问题要讲清楚)
class SingletonLazy1{private static volatile SingletonLazy1 instance = null;private SingletonLazy1(){}public static SingletonLazy1 getInstance(){if (instance==null){synchronized (SingletonLazy1.class){if(instance==null){instance=new SingletonLazy1();}}}return instance;}
}
下面这个图片非常重要,解释了重要的逻辑
理解双重if判定/volatile:
加锁/解锁是一件开销比较高的事情,而懒汉模式的线程不安全只是发生在首次创建实例的时候,因此后续使用的时候就不必再进行加锁了
外层的if就是判定下看当前是否把Instance实例创建出来了
同时为了避免“内存可见性”导致读取的Instance出现偏差,于是补充上volatile
当多线程首次调用getInstance,大家可能都发现Instance为null,于是又继续往下执行来竞争锁,其中竞争成功的线程再完成创建实例的操作
当这个实例创建完了之后,其他竞争锁的线程就被里层if挡住了,也就不会继续创建其他实例
我们通过一个更形象的例子来理解这个问题
1️⃣:有三个线程,开始执行getInstance
,通过外层的if(instance==null)
知道了实例还没有创建的消息,于是开始竞争同一把锁
2️⃣:其中线程1率先获取到锁,此时线程1通过里层的if(instance==null)
进一步确认实例是否已经创建,如果没有创建,就把这个实例创建出来
3️⃣:当线程1释放锁之后,线程2和线程3也拿到锁,也通过里层的if(instance==null)
来确认实例是否已经创建,发现实例已经创建出来了,就不再创建了
4️⃣:后续的线程,不必加锁,直接就通过外层if(instance==null)
就知道实例已经创建了,从而不再尝试获取锁了,降低了开销
相关文章:
多线程系列五:面试中常考的单例模式
1.设计模式 在了解单例模式之前我们先要了解设计模式: 设计模式是一种软性规定,遵守了设计模式,代码的下限就被兜住了,类似于棋谱,是大佬设计出来的,让小白程序员也能写出好的代码 设计模式有很多种&#x…...
音视频之H.265/HEVC编解码并处理
H.265/HEVC系列文章: 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 4、音视频之H.265/HEVC变换编码 5、音视频之H.265/HEVC量化 6、音视频之H.265/HEVC环路后处理 7、音视频之H.265/HEVC熵编…...
Python入门(一)
目录 一、Python数据类型 1.字面量 2.注释 3.变量 4.数据类型 二、 运算符 1.数据类型之间的相互转换 2 算数运算符 3、逻辑运算符 三、判断语句 if 四、循环 1、while循环 2、for循环 2.1 for...else... 五、格式化字符串 1.字符串 1.1创建字符串的方式&…...
2025年01月09日德美医疗前端面试
目录 vue2 的双向绑定的原理vue3 的双向绑定原理vue 的生命周期vue 子组件为何不能修改父组件的值js delete 删除数组的某一个值会怎么样vue 和 react 的 diff 算法什么是闭包原型链this指向 vue2 的双向绑定的原理 以下是 Vue 2 双向绑定的原理: 1. 核心概念 …...
02 mysql 管理(Windows版)
一、启动及关闭 MySQL 服务器 1.1 通过 “服务” 管理工具 winr打开运行,输入services.msc 找到MySQL80,这个是我们在安装mysql的时候给的服务的名称,具体见文章mysql 安装 右键选择启动或者停止。 1.2 通过命令提示符 1.2.1 关闭命令…...
开发搭载OneNet平台的物联网数据收发APP的设计与实现
一、开发环境与工具准备 工具安装 下载HBuilderX开发版(推荐使用开发版以避免插件兼容性问题)安装Node.js和npm(用于依赖管理及打包)配置Android Studio(本地打包需集成离线SDK)项目初始化 创建uni-app项目,选择“默认模板”或“空白模板”安装必要的UI库(如uView或Van…...
ntdll!LdrpInitializeProcess函数分析之Peb->Ldr和全局变量ntdll!PebLdr的关系
代码部分A: PEB_LDR_DATA PebLdr; //全局变量ntdll!PebLdr NTSTATUS LdrpInitializeProcess ( IN PCONTEXT Context OPTIONAL, IN PVOID SystemDllBase ) { 代码部分B: // // Figure out process name. // Teb NtCurrentTeb…...
如何开始使用 Blender:Blender 3D 初学者指南和简介 怎么下载格式模型
Blender 是一个强大的 3D 创作套件,为动画、视觉效果、艺术等提供了一系列功能。无论您是初学者还是经验丰富的艺术家,Blender 都提供了一个免费的开源平台来释放您的创造力。凭借其内置的视频序列编辑器,Blender 还提供基本的编辑功能&#…...
Nginx安全防护与HTTPS部署
目录 一、Nginx 概述 二、Nginx 核心安全配置 (一)编译安装 Nginx (二)隐藏版本号 (三)限制危险请求方法 (四)请求限制(CC 攻击防御) (五&…...
HTTP 与 HTTPS 的深度剖析:差异、原理与应用场景
HTTP 与 HTTPS 的深度剖析:差异、原理与应用场景 在互联网的世界里,HTTP(超文本传输协议)和 HTTPS(超文本传输安全协议)是数据传输的 “高速公路”,它们承载着我们日常浏览网页、购物支付等各种…...
SMT贴片钢网精密设计与制造要点解析
内容概要 SMT贴片钢网作为电子组装工艺的核心载体,其设计与制造质量直接影响焊膏印刷精度及产品良率。本文系统梳理了钢网全生命周期中的15项关键技术指标,从材料选择、结构设计到工艺控制构建完整技术框架。核心要点涵盖激光切割精度的微米级调控、开口…...
算法每日一题 | 入门-顺序结构-三角形面积
三角形面积 题目描述 一个三角形的三边长分别是 a、b、c,那么它的面积为 p ( p − a ) ( p − b ) ( p − c ) \sqrt{p(p-a)(p-b)(p-c)} p(p−a)(p−b)(p−c) ,其中 p 1 2 ( a b c ) p\frac{1}{2}(abc) p21(abc) 。输入这三个数字,…...
Linux内核视角:线程同步与互斥的原理、实现与锁优化策略
Linux系列 文章目录 Linux系列前言一、前提知识二、线程互斥概念引入三、线程互斥3.1 什么是线程的互斥3.2 线程互斥的实现 四、锁的实现原理 前言 在前两篇文章中,我们已经对线程的相关概念及基本操作进行了深入介绍。在本篇中,我们将深入探讨编写多线…...
【区块链】Uniswap详细介绍
一、前言 本文将结合网上的资料和博主的理解,像大家详细介绍Uniswap,包括其核心概念、工作原理、版本演进、代币经济学以及风险点,适合想深入了解去中心化交易所(DEX)机制的用户。 二、Uniswap是什么 Uniswap 是一个…...
YOLOv8的Python基础--函数篇
1. 文件/目录操作相关函数 这些函数来自 os 和 shutil 模块: 函数/用法作用示例说明os.listdir(dir)列出目录下所有文件名os.listdir("./images")返回文件名列表(不包含路径)os.path.join()拼接路径os.path.join("dir"…...
vue源代码采用的设计模式分解
No.大剑师精品GIS教程推荐0地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 1Openlayers 【入门教程】 - 【源代码示例 300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3MapboxGL【入门教程】 - 【源代码图文示例150】 4Cesium 【入门教程】…...
强化学习是AI Agent的进化引擎还是技术枷锁呢?
第一章 强化学习:Agent的“灵魂”觉醒之路 1.1 AlphaGo的启示:从规则到目标驱动的范式革命 2016年AlphaGo击败李世石的事件,标志着RL首次在复杂决策场景中展现其颠覆性价值。通过深度神经网络与RL的结合,AlphaGo无需依赖人类棋谱…...
python简易实现勒索病毒
python简易实现勒索病毒 1.首先介绍Crypto库1.1首先是对称加密1.2 非对称加密1.3 哈希 2.生成RSA密钥并保存3.文件加密4.文件解密1. 导入必要的模块2. 定义解密函数3. 设置私钥的密码4. 打开并读取文件5. 导入私钥6. 读取加密数据7. 解密会话密钥8. 创建 AES 解密器9. 解密数据…...
Nacos源码—4.Nacos集群高可用分析三
大纲 6.CAP原则与Raft协议 7.Nacos实现的Raft协议是如何写入数据的 8.Nacos实现的Raft协议是如何选举Leader节点的 9.Nacos实现的Raft协议是如何同步数据的 10.Nacos如何实现Raft协议的简版总结 6.CAP原则与Raft协议 (1)CAP分别指的是什么 (2)什么是分区以及容错 (3)为…...
AWS WebRTC如何实现拉流?内部是这样实现的
当我们通过手机上的app选择某一个Iot设备,例如,摄像头,想看实时视频的时候,aws都做了什么?最近在搞自研Iot项目,借机整理一下相关流程。 App通过 AWS SDK 发起拉流请求的内部机制是AWS Kinesis Video Streams (KVS) WebRTC 模式中一个非常关键的问题。 一、KVS WebRTC …...
NGINX `ngx_http_browser_module` 深度解析与实战
1. 模块定位 ngx_http_browser_module 在 HTTP 头 User-Agent 解析的基础上,给出三个内置变量: 变量作用典型值$modern_browser当 UA 被判定为 现代浏览器 时取 modern_browser_value 指定的值;否则为空modern. / 1$ancient_browser当 UA 被…...
Elasticsearch知识汇总之 ElasticSearch高可用方案
六 ElasticSearch高可用方案 6.1 高可用架构 请求协调节点根据负载均衡,转发给主分片节点,主分片同步复制给从节点,主从节点都写入完成返回客户端请求成功。对于读请求,协调负载到任意节点数据节点,数据节点把各自符合…...
多线程2-多线程编程
引入 当我们想要代码能够实现并发执行时,我们可以使用多进程进行并发编程(在Java中并不推荐这种方式,许多API在Java标准库中都没有提供),也可以使用多线程进行并发编程(系统提供了相关的API,Ja…...
电商系统中单商户和多商户的区别
在电商的商业版图上,单商户与多商户模式如同两条并行的发展脉络,各自构建起独特的商业生态。它们在运营逻辑、商业模式等多方面存在显著差异,这些差异不仅塑造了不同的平台特性,也深刻影响着企业的发展路径。接下来,我…...
【东枫科技】代理英伟达产品:智能网卡的连接线
文章目录 总览详细:NVIDIA 400Gb/s QSFP-DD 线缆详细:NVIDIA 400Gb/s OSFP 线缆详细:NVIDIA 200Gb/s QSFP56 线缆详细:NVIDIA 100Gb/s QSFP28 线缆 总览 详细:NVIDIA 400Gb/s QSFP-DD 线缆 详细:NVIDIA 400…...
使用ip池后,爬虫还被封,是什么原因呢?
嘿,亲爱的小伙伴们!今天我们聊一个让很多爬虫工程师抓狂的问题:明明用上了IP池,结果爬虫还是被封了!怎么回事呢?如果你也曾在爬虫与反爬的“猫鼠游戏”里痛苦“翻车”,别着急,这篇文…...
C++23 新利器:深入解析栈踪迹库 (P0881R7)
文章目录 为何需要标准化的栈踪迹?P0881R7 的核心组件与使用基本用法示例与异常处理的集成优势与价值潜在的考量总结 对于 C 开发者而言,调试和错误诊断一直是开发周期中不可或缺但又充满挑战的一环。当程序崩溃或发生未预期行为时,获取清晰、…...
2025-05-06 事业-独立开发项目-记录
摘要: 2025-05-06 事业-独立开发项目-记录 独立开发项目记录 Product Hunt | InDev 独立开发者导航站https://www.producthunt.com/ Nomads.com - Best Places to Live for Digital Nomads (formerly Nomad List)https://nomads.com/ InDev 独立开发者导航站https://indev.bei…...
【Linux系统】探索进程等待与程序替换的奥秘
文章目录 前言一、重谈进程创建1.1 fork 函数1.2 写时拷贝1.3 fork 的常规用法1.4 fork 调用失败的原因1.5 创建一批进程 二、进程终止2.1 进程退出场景2.2 strerror 函数的作用2.3 errno 全局变量2.4 程序异常机制2.5 进程退出方式 三、进程等待3.1 进程等待必要性3.2 进程等待…...
Github 2025-05-06Python开源项目日报 Top10
根据Github Trendings的统计,今日(2025-05-06统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10C++项目2TypeScript项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…...
【愚公系列】《Manus极简入门》021-音乐创作助手:“音符魔术师”
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
【Azure Redis】Redis导入备份文件(RDB)失败的原因
问题描述 在测试Azure Redis的导入/导出备份文件的功能中,突然发现在Redis 4.0上导入的时候,一直报错。 image.png 问题解答 因为门户上只是显示导入失败,没有任何错误消息说明。根据常理推断,Redis 的RDB文件格式都具有一致性。居…...
git “分离头指针”(detached HEAD) 状态。
在 Git 中,当你运行 git branch 命令时,看到如下输出: * (detached from 5b596b5)master 其中的: * (detached from 5b596b5) 表示你当前处于 “分离头指针”(detached HEAD) 状态。 🧠 什…...
Gitee的介绍
目录 1.Gitee介绍: 1.1 代码托管 1.2 本土化优势 1.3 企业级服务 1.4 开源生态 1.5 多形态适配 定位:国内开发者首选的高效代码协作平台,兼顾个人开源与企业级私有开发需求。 2.Gitee和GitHub区别 3.Gitee使用教程 4.Gitee相关…...
NoUniqueKey问题和Regular join介绍
问题背景 在flink任务中,遇到了 NoUniqueKey Join的情况,导致了数据膨胀,和下游结果与数据库数据不一致问题 那NoUniqueKey Join为什么会导致问题呢,下面是其中一种场景示例: 为什么会出现 NoUniqueKey :…...
TC8:SOMEIP_ETS_027-028
SOMEIP_ETS_027: echoUINT8 目的 检查method方法echoUINT8的参数及其顺序能够被顺利地发送和接收 说白了就是检查UINT8数据类型参数在SOME/IP协议层的序列化与反序列化是否正常。 UINT8相比于测试用例SOMEIP_ETS_021: echoINT8中的SINT8数据类型来说,属于无符号整数,也就是…...
小微企业SaaS ERP管理系统,SpringBoot+Vue+ElementUI+UniAPP
小微企业的SaaS ERP管理系统,ERP系统源码,ERP管理系统源代码 一款适用于小微企业的SaaS ERP管理系统, 采用SpringBootVueElementUIUniAPP技术栈开发,让企业简单上云。 专注于小微企业的应用需求,如企业基本的进销存、询价&#…...
css filter 常用方法函数和应用实例
1. blur() 模糊 filter: blur(半径);参数:模糊半径(像素),值越大越模糊 示例:filter: blur(5px);2. brightness() 亮度 filter: brightness(百分比); 参数:1原始对比度,0全灰,>…...
chrome inspect 调试遇到的问题
1、oppp 手机打开webview 的时候, 报错这个并没有页面 Offline #V8FIG6SGLN75M7FY Pending authentication: please accept debugging session on the device. 解决方法,保持chrome 浏览器在显示的状态 去设置里开启usb 调试再关闭,反复重…...
Kotlin 中 List 和 MutableList 的区别
在 Kotlin 中,List 和 MutableList 是两种不同的集合接口,核心区别在于可变性。 Kotlin 集合框架的重要设计原则:通过接口分离只读(read - only)和可变(mutable)操作,以提高代码的安…...
openssl 生成自签名证书实现接口支持https
1.下载安装openssl Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 2.配置环境变量 将 openssl 的目录(D:\tools\openssl\bin)添加到 path 中 3.生成自签名证书 找一个存证书的目录打开powershell 3.1 生成私钥 openssl gen…...
React 中集成 Ant Design 组件库:提升开发效率与用户体验
React 中集成 Ant Design 组件库:提升开发效率与用户体验 一、为什么选择 Ant Design 组件库?二、基础引入方式三、按需引入(优化性能)四、Ant Design Charts无缝接入图标前面提到了利用Redux提供全局维护,但如果在开发时再自己手动封装组件,不仅效率不高,可能开发的组件…...
神经网络:节点、隐藏层与非线性学习
神经网络:节点、隐藏层与非线性学习 摘要: 神经网络是机器学习领域中一种强大的工具,能够通过复杂的结构学习数据中的非线性关系。本文从基础的线性模型出发,逐步深入探讨神经网络中节点和隐藏层的作用,以及它们如何…...
vue+tsc+noEmit导致打包报TS类型错误问题及解决方法
项目场景: 提示:这里简述项目相关背景: 当我们新建vue3项目,package.json文件会自动给我添加一些配置选项,这写选项基本没有问题,但是在实际操作过程中,当项目越来越复杂就会出现问题,本文给大家分享vuetscnoEmit导致打包报TS类型错误问题及…...
Ragflow服务器上部署教程
参考官方文档进行整理 克隆相应代码 git clone https://github.com/infiniflow/ragflow.git修改vm.max_map_count sudo sysctl -w vm.max_map_count262144修改 daemon.json文件 {"registry-mirrors": ["https://docker.m.daocloud.io","https://0…...
Ubuntu 系统中解决 Firefox 中文显示乱码的完整指南
Firefox 是一款流行的网络浏览器,但在 Ubuntu 系统中有时会遇到中文显示乱码的问题。本文将为您提供一个全面的解决方案,帮助您轻松解决这个烦人的问题。 问题概述 在 Ubuntu 系统中使用 Firefox 浏览器时,有时会发现中文字符显示为乱码或方块。这通常是由于缺少合适的中文…...
JVM——垃圾回收
垃圾回收 在Java虚拟机(JVM)的自动内存管理中,垃圾回收(Garbage Collection, GC)是其核心组件之一。它负责回收堆内存中不再使用的对象所占用的内存空间,以供新对象的分配使用。下面我们将深入探讨JVM中的…...
【AI News | 20250506】每日AI进展
AI Repos 1、gitsummarize GitSummarize是一个在线工具,用户只需将GitHub URL中的“hub”替换为“summarize”,即可为任何公开或私有代码库生成交互式文档。该工具利用Gemini分析代码结构,自动生成系统级架构概述、目录和文件摘要、自然语言…...
LabVIEW高冲击加速度校准系统
在国防科技领域,高 g 值加速度传感器广泛应用于先进兵器研制,如深侵彻系统、精确打击弹药及钻地弹药等。其性能指标直接影响研究结果的准确性与可靠性,因此对该传感器进行定期校准意义重大。高冲击加速度校准系统具备多方面功能,适…...
优化算法 - intro
优化问题 一般形式 minimize f ( x ) f(\mathbf{x}) f(x) subject to x ∈ C \mathbf{x} \in C x∈C 目标函数 f : R n → R f: \mathbb{R}^n \rightarrow \mathbb{R} f:Rn→R限制集合例子 C { x ∣ h 1 ( x ) 0 , . . . , h m ( x ) 0 , g 1 ( x ) ≤ 0 , . . . , g r …...