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

【多线程初阶】多线程案例之单例模式

文章目录

  • 前言
  • 1. 什么是单例模式
  • 2. 饿汉模式
  • 3. 懒汉模式 --- 单线程版
  • 4. 懒汉模式 --- 多线程版
  • 5. 懒汉模式 --- 多线程改进版
  • 总结


前言

本文主要给大家讲解多线程的一个重要案例 — 单例模式.

关注收藏, 开始学习吧🧐


1. 什么是单例模式

单例模式是一种很经典的设计模式, 那么什么叫做设计模式呢?

设计模式好比象棋中的 “棋谱”.
红方当头炮, 黑方马来跳. 针对红方的一些走法, 黑方应招的时候有一些固定的套路. 按照套路来走局势就不会吃亏.
软件开发中也有很多常见的 “问题场景”. 针对这些问题场景, 大佬们总结出了一些固定的套路. 按照这个套路来实现代码, 也不会吃亏.

单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例.

这一点在很多场景上都需要. 比如 JDBC 中的 DataSource 实例就只需要一个.

单例模式具体的实现方式有很多种写法, 在这里我们主要讲解 “饿汉”“懒汉” 两种.

2. 饿汉模式

核心思想: 类加载的同时, 创建实例.

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

注意:

  1. private static Singleton instanse = new Singleton(); 被 static 修饰, 该属性是类的属性, JVM 中, 每个类的类对象只有唯一一份, 类对象里的这个成员自然也是唯一一份了.
  2. private Singleton() {}; 将构造方法设为 private, 就可以将外部的 new 操作给禁用掉.
  3. 此时, 在类内部把实例创建好, 同时禁止外部重新创造实例, 就可以保证单例的特性了.

在这里插入图片描述
由于构造方法设为 private, 导致 new 操作被禁用, 我们只能通过类方法 .getInstanse 来创建实例, 可以看到, 这样先后创建的 s1 和 s2 实例, 其实是同一个实例.

3. 懒汉模式 — 单线程版

核心思想: 类加载的时候不创建实例. 第一次使用的时候才创建实例.

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

注意点与饿汉模式差不多, 但是区别在于, 懒汉模式是 “非必要不创建”, 可以看到, instance 实例对象是在调用类方法时才创建的.

4. 懒汉模式 — 多线程版

现在问题来了, 上述两个模式, 是否能构保证线程安全呢?

多个线程下调用 getInstance 方法, 是否会出现问题呢?

回想一下我们之前讲解的线程不安全的几个原因. 可以推断饿汉模式下, 线程是安全的, 因为他只是读数据, 并没有进行写数据.

但是多线程下, 懒汉模式可能无法保证创建对象的唯一性, 线程不安全.

线程安全问题发生在首次创建实例时. 如果在多个线程中同时调用 getInstance 方法, 就可能导致创建出多个实例.
一旦实例已经创建好了, 后面再多线程环境调用 getInstance 就不再有线程安全问题了(不再修改instance 了)

我们可以通过加锁, 利用 synchronized 关键字就可以改善这里的线程安全问题.

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

5. 懒汉模式 — 多线程改进版

加锁其实是一个比较低效的操作, 因为他会造成阻塞等待, 非必要还是不要进行加锁.

以下代码在加锁的基础上, 做出了进一步改动:

  • 使用双重 if 判定, 降低锁竞争的频率.
  • 给 instance 加上了 volatile.
class SingletonLazy {private static volatile SingletonLazy instance = null;public static SingletonLazy getInstance() {if (instance == null) {synchronized (SingletonLazy.class) {if (instance == null) {instance = new SingletonLazy();}}}return instance;}private SingletonLazy() {};
}

理解双重 if 判定 / volatile:

加锁 / 解锁是一件开销比较高的事情. 而懒汉模式的线程不安全只是发生在首次创建实例的时候. 因此后续使用的时候, 不必再进行加锁了.

  • 外层的 if 就是判定下看当前是否已经把 instance 实例创建出来了.
  • 同时为了避免 “内存可见性” 导致读取的 instance 出现偏差, 于是补充上 volatile .
  • 当多线程首次调用 getInstance, 大家可能都发现 instance 为 null, 于是又继续往下执行来竞争锁, 其中竞争成功的线程, 再完成创建实例的操作.
  • 当这个实例创建完了之后, 其他竞争到锁的线程就被里层 if 挡住了. 也就不会继续创建其他实例.
  • 有三个线程, 开始执行 getInstance , 通过外层的 if (instance == null) 知道了实例还没有创建的消息. 于是开始竞争同一把锁.

总结

✨ 本文讲解了线程安全下的单例模式, 由于饿汉模式只是读操作, 天生就是安全的, 而懒汉模式不是安全的, 因为有写操作, 我们通过加锁, 并利用双重 if 来减少不必要的加锁操作, 再使用 volatile 禁止指令重排序, 使其变得安全.
✨ 想了解更多的多线程知识, 可以收藏一下本人的多线程学习专栏, 里面会持续更新本人的学习记录, 跟随我一起不断学习.
✨ 感谢你们的耐心阅读, 博主本人也是一名学生, 也还有需要很多学习的东西. 写这篇文章是以本人所学内容为基础, 日后也会不断更新自己的学习记录, 我们一起努力进步, 变得优秀, 小小菜鸟, 也能有大大梦想, 关注我, 一起学习.

再次感谢你们的阅读, 你们的鼓励是我创作的最大动力!!!!!

相关文章:

【多线程初阶】多线程案例之单例模式

文章目录 前言1. 什么是单例模式2. 饿汉模式3. 懒汉模式 --- 单线程版4. 懒汉模式 --- 多线程版5. 懒汉模式 --- 多线程改进版总结 前言 本文主要给大家讲解多线程的一个重要案例 — 单例模式. 关注收藏, 开始学习吧🧐 1. 什么是单例模式 单例模式是一种很经典的…...

跨境选品怎么选?建议独立站卖家收下这份利基产品查找攻略!

跨境电商平台现在可谓是火热发展中,独立站出海风口,其实选择的机会还真不少,相比国内电商的发展势头,看得出来,未来跨境电商的大门,对你而言,敞开着。选品这事儿,就像你上战场前挑选…...

[C++项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍...

项目背景 Boost库是C中一个非常重要的开源库. 它实现了许多C标准库中没有涉及的特性和功能, 一度成为了C标准库的拓展库. C新标准的内容, 很大一部分脱胎于Boost库中. Boost库的高质量代码 以及 提供了更多实用方便的C组件, 使得Boost库在C开发中会被高频使用 为方便开发者学…...

opencv-32 图像平滑处理-高斯滤波cv2.GaussianBlur()

在进行均值滤波和方框滤波时,其邻域内每个像素的权重是相等的。在高斯滤波中,会将中心点的权重值加大,远离中心点的权重值减小,在此基础上计算邻域内各个像素值不同权重 的和。 基本原理 在高斯滤波中,卷积核中的值不…...

Windows 环境Kubernetes安装

目录 前言 安装 Docker 安装 Kubernetes Windows 安装 kubectl 介绍 安装 开启 Kubernetes 前言 Docker作为当前最流行的容器化平台,为Kubernetes提供了强大的容器化技术基础。Kubernetes与Docker的结合,使得容器化应用程序在大规模集群中得以简…...

自建类ChatGPT服务:本地化部署与远程访问教程

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...

常用SQL语句总结

SQL语句 文章目录 SQL语句1 SQL语句简介2 DQL(数据查询语句)3 DML(数据操纵语句)4 DDL(数据定义语句)5 DCL(数据控制语句)6 TCL(事务控制语句) 1 SQL语句简介…...

arm交叉编译lmbench

一、下载lmbench www.bitmover.com/lmbench 官网下载,http://www.bitmover.com/lmbench/lmbench3.tar.gz 我没有下载下来,找的别人的百度云下载 链接: https://pan.baidu.com/s/1tGo1clCqY-jQPN8G1eWSsg 提取码: f6jd 二、修改makefile 修改三个文件…...

ExtJs 7.7.0 下载方法与去除trial水印

背景 最近发现Sencha ExtJs发布了ExtJs7.7.0版本,立刻下载了SDK包,许多朋友不知如何下载,如何去除右上角的trial水印。本文讲下相关下载技巧与方法。 下载SDK 首先需要申请试用,申请地址如下,需要注意可能需要梯子&…...

Android11开发规划

文章目录 规划总结规划 提示:这里可以添加本文要记录的大概内容: 从本文开始,会介绍如何移植瑞芯微提供的Android11源码到自己的RK3568的板子上 下面是整个Android开发的规划: 包括以下部分: … 一、移植部分 下载编译瑞芯微提供的源码 瑞芯微原厂源码目录介绍...

活动隔断在现在酒店运用的方式

活动隔断是一种在酒店内部划分空间的方式,用于实现不同活动的隔离和隐私。现代酒店常用的活动隔断方式有以下几种: 1. 固定隔断:使用墙体、固定屏风或者板材等材料,将空间划分为不同的房间或区域。这种方式常用于划分客房、会议室…...

Jenkins工具系列 —— 插件 钉钉发送消息

文章目录 安装插件 Ding TalkJenkins 配置钉钉机器人钉钉APP配置项目中启动钉钉通知功能 安装插件 Ding Talk 点击 左侧的 Manage Jenkins —> Plugins ——> 左侧的 Available plugins Jenkins 配置钉钉机器人 点击 左侧的 Manage Jenkins ,拉到最后 钉…...

LeetCode 26 题:删除有序数组的重复项

思路 在写这一个题时,我突然想到了Python中的 set()函数可能会有大用处,便选择了用Python写。 set()函数可以将列表转化为集合,集合会保证元素的单一性,所以会自动删去相同字符。 …...

优雅地切换node版本(windows)

文章目录 1、下载并安装nvm2、nvm的使用3、处理npm版本与nodejs版本不匹配问题(通常不会有这个问题) 1、下载并安装nvm 卸载已安装的node:控制面板-程序-找到node并卸载 通常在控制面板中卸载后,nodejs目录、环境变量、注册表就自…...

反诈:吴明军、黄亮领导的WIN生活资金盘,大家警惕防范此类诈骗

消息已经证实!“米粒”无法变现,数以万计的会员深套“315万民商城”,维权艰难,血汗钱无法讨回。 其实这一点笔者并不感到太意外,因为万民商城资金传销盘的定性之前就已经发文揭露过,并反复提醒大家小心警惕…...

shell、bash的关系及bash的特性(一)

一、概念 shell是壳,是运行在终端中的文本互动程序。Shell相当于是一个翻译,把我们在计算机上的操作命令,翻译为计算机可识别的二进制命令,传递给内核,以便调用计算机硬件执行相关的操作;同时,计…...

【问题随记】

ubuntu 14.04源更新(sources.list) deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-update…...

Stable Diffusion AI绘画学习指南【常用模型,采样器介绍】

常用采样器、目前有20个采样步骤越多每个步之间的降噪越小,减少采样过程中的截断误差,结果越好 学微分方程求解器 Euler(最简单的采样器,采样过程中不加随机噪声,根据采样计划来执行每个步骤中的噪声,并使…...

pycharm——漏斗图

import pyecharts.options as opts from pyecharts.charts import Funnel""" Gallery 使用 pyecharts 1.1.0 参考地址: https://echarts.apache.org/examples/editor.html?cfunnel目前无法实现的功能:1、暂时无法对漏斗图的长宽等范围操作进行修改 ""…...

RISC-V基础之浮点指令(包含实例)

RISC-V体系结构定义了可选的浮点扩展,分别称为RVF、RVD和RVQ,用于操作单精度、双精度和四倍精度的浮点数。RVF/D/Q定义了32个浮点寄存器,f0到f31,它们的宽度分别为32位、64位或128位。当一个处理器实现了多个浮点扩展时&#xff0…...

Windows与Office激活革命:KMS_VL_ALL_AIO智能解决方案深度解析

Windows与Office激活革命:KMS_VL_ALL_AIO智能解决方案深度解析 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 你是否曾为Windows系统或Office办公软件那恼人的"需要激活"…...

、SEATA分布式事务——XA模式遣

MySQL 中的 count 三兄弟:效率大比拼! 一、快速结论(先看结论再看分析) 方式 作用 效率 一句话总结 count(*) 统计所有行数 最高 我是专业的!我为统计而生 count(1) 统计所有行数 同样高效 我是 count(*) 的马甲兄弟…...

中小企业必看:Gemma 4 企业级私有化部署全流程(避坑指南)

中小企业必看:Gemma 4 企业级私有化部署全流程(避坑指南) 前言 对中小企业来说,AI大模型不用追求“参数越高越好”,核心是“低成本、易部署、能商用、保隐私”——而谷歌最新开源的Gemma 4,刚好踩中所有痛…...

告别卡顿:如何让Mac外接鼠标获得原生触控板的顺滑滚动体验

告别卡顿:如何让Mac外接鼠标获得原生触控板的顺滑滚动体验 【免费下载链接】Mos 一个用于在 macOS 上平滑你的鼠标滚动效果或单独设置滚动方向的小工具, 让你的滚轮爽如触控板 | A lightweight tool used to smooth scrolling and set scroll direction independent…...

2026届最火的五大AI论文工具横评

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 借助人工智能来辅助撰写开题报告,可显著提高研究框架构建的效率,在用…...

hadoop+Spark+Java基于搜索日志的图文推荐系统设计(源码+文档+调试+可视化大屏)

前言本文介绍了一款使用spring boot开发的搜索日志的图文推荐,及其设计与实现过程。根据软件工程对软件系统开发定制的规则和标准,详细的介绍了系统的分析与设计过程,并且详细的概括了系统的开发与测试过程,将其与JAVA语言紧密结合…...

免费NTFS读写终极指南:三分钟让Mac完美支持Windows硬盘

免费NTFS读写终极指南:三分钟让Mac完美支持Windows硬盘 【免费下载链接】Free-NTFS-for-Mac Nigate: An open-source NTFS utility for Mac. It supports all Mac models (Intel and Apple Silicon), providing full read-write access, mounting, and management f…...

Input Leap架构深度解析:跨平台KVM软件的技术实现与多设备输入协同

Input Leap架构深度解析:跨平台KVM软件的技术实现与多设备输入协同 【免费下载链接】input-leap Open-source KVM software 项目地址: https://gitcode.com/gh_mirrors/in/input-leap 在现代多设备办公环境中,Input Leap作为一款开源的KVM&#x…...

Obsidian LiveSync技术全景:自托管同步插件的深度解析与架构揭秘

Obsidian LiveSync技术全景:自托管同步插件的深度解析与架构揭秘 【免费下载链接】obsidian-livesync 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-livesync Obsidian LiveSync作为一款社区驱动的自托管同步插件,为Obsidian用户提供了…...

避开滑模控制的5个大坑:从切换函数设计到抖振抑制的避坑指南

避开滑模控制的5个大坑:从切换函数设计到抖振抑制的避坑指南 滑模控制因其强鲁棒性和对参数变化的不敏感性,已成为非线性控制领域的重要工具。但在实际工程应用中,许多开发者常陷入一些典型陷阱,导致系统性能下降甚至失控。本文将…...