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

Java Web 实战 07 - 多线程基础之单例模式

大家好 , 这篇文章给大家带来的是单例模式 , 单例模式中分为懒汉模式和饿汉模式 , 懒汉模式是需要用的到的时候才去创建实例 , 而饿汉模式是程序一启动就立刻创建实例 , 在这其中还有很多其他问题需要我们去研究
推荐大家跳转到这里 , 观看效果更加
上一篇文章的链接我也贴在这里了
在这里插入图片描述

单例模式

  • 单例模式
  • 1. 饿汉模式 : 程序启动立即创建实例
  • 2. 懒汉模式 : 程序启动先不创建实例 , 等到真正有用的时候再创建实例
  • 3. 正题 : 上述的两个单例模式的代码在多线程环境下调用 getInstance() 是线程安全的吗?

单例模式

单例模式是一种非常常见的设计模式

设计模式就相当于棋谱 , 前人总结出的一些固定套路 , 如果我们按照这些固定套路 , 代码就不会写的太离谱

设计模式虽然很有用 , 但是需要大家有一定的编程经验才好理解一点
未来肯定会经常和设计模式打交道 , 但是现在我们还是学习一下面试中比较常见的设计模式
校招中 , 关于设计模式 , 主要考察两个 : 单例模式、工厂模式

单例模式的目的就是 : 有些对象 , 在一个程序中应该只有一个实例 , 就可以使用单例模式
在单例模式下 , 对象的实例化就被限制了 , 只能创建一个 , 多的就不能再创建了

单例模式就是借助相关语法强制限制咱们不能创建多个实例

开车为啥要系安全带 ?
大家都不想出现事故 , 但是通过司机并不能完全保证安全
所以就出现了安全带 , 一定程度上保证了安全

在 Java 中 , 单例模式有很多种实现方式
我们主要介绍两个 : 饿汉模式 和 懒汉模式
他们俩描述的是 创建实例的时机
饿汉模式 : 程序启动立即创建实例
懒汉模式 : 程序启动先不创建实例 , 等到真正有用的时候再创建实例

大家不要把懒理解成贬义词 , 在计算机中 , 懒这个字往往意味着性能比较高
许多科技的发明都是因为人类懒 , 想要方便生活

计算机中 , 这种思想很常见
硬盘里面有许多大文件
使用文件资源管理器打开它

  1. 饿汉模式 : 把这些大文件通通读到内存中 , 读取完毕之后再让用户进行查看和修改
  2. 懒汉模式 : 只读取出当前页面能显示出的范围的文件数目 , 随着用户翻页 , 继续再读后面内容 , 用户还没翻到 , 就不着急度

或者刷抖音 , 不是一下子加载出所有的视频 , 而是一个一个加载 , 刷完了再加载下一条
或者微信朋友圈 , 只有当你点进去的时候 , 才会加载原图 , 否则就不加载

1. 饿汉模式 : 程序启动立即创建实例

// 单例模式的实现
// 饿汉模式
class Singleton {// 创建实例,把创建的实例赋值给一个静态变量// 静态变量又叫做类变量,类对象在整个程序中只有唯一一个实例->保证了单例private static Singleton instance = new Singleton();// 通过这个静态方法返回独苗实例// 后续如果需要使用这个实例,统一基于getInstance方法来获取咱们的独苗实例,就不需要去new了public static Singleton getInstance() {return instance;}// 构造方法设为私有:其他的类想来new就不行了// 从根本上禁止了其他代码来new Singleton 实例了private Singleton() {}
}public class Demo19 {public static void main(String[] args) {Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();// 创建的是同一个实例System.out.println(instance1 == instance2);// true}
}

如果我们再手动创建一个实例 , 就会报错
image.png

单例模式的关键是 : 使用静态成员表示实例 (唯一性) + 让构造方法为私有 (堵住了 new 创建新实例的方式)

那么这段代码为什么说是饿汉模式呢 ?
image.png

2. 懒汉模式 : 程序启动先不创建实例 , 等到真正有用的时候再创建实例

// 单例模式的实现
// 懒汉模式
class SingletonLazy {// 先不着急实例化private static SingletonLazy instance = null;public static SingletonLazy getInstance() {// 进行判断// 为空->创建实例if(instance == null) {instance = new SingletonLazy();}return instance;}// 构造方法同样也是 private 的private SingletonLazy() {}
}public class Demo19 {public static void main(String[] args) {Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();}
}

image.png

3. 正题 : 上述的两个单例模式的代码在多线程环境下调用 getInstance() 是线程安全的吗?

饿汉模式是天然线程安全的
image.png
懒汉模式是线程不安全的
image.png
懒汉模式一旦实例创建好之后 , 后续 if 条件就进不去了 , 此时也就全是读操作了 , 也就线程安全了
所以我们要是想让懒汉模式变成线程安全的 , 就一定要解决第一次创建实例的过程

那如何解决懒汉模式的线程不安全问题呢 ?
解决办法就是加锁

// 单例模式的实现
// 懒汉模式
class SingletonLazy {// 先不着急实例化private static SingletonLazy instance = null;public static SingletonLazy getInstance() {// 进行判断// 为空->创建实例synchronized (SingletonLazy.class) {if(instance == null) {instance = new SingletonLazy();}}return instance;}// 构造方法同样也是 private 的private SingletonLazy() {}
}public class Demo19 {public static void main(String[] args) {Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();}
}

image.png
但是目前还是有问题
懒汉模式只是初始情况下 , 才会有线程不安全问题
一旦实例创建好了之后 , 此时就安全了
既然如此 , 后续再调用 getInstance 的时候就不应该再去加锁了
当线程已经安全了 , 我们再尝试进行加锁 , 其实就非常影响效率了
所以我们需要做到 : 该加锁的地方需要加锁 , 不该加锁的时候别乱加锁
我们只需要再加上一层 if 判定就 ok 了

// 单例模式的实现// 懒汉模式
class SingletonLazy {// 先不着急实例化private static SingletonLazy instance = null;public static SingletonLazy getInstance() {// 进行判断// 为空->创建实例if(instance == null) {synchronized (SingletonLazy.class) {if(instance == null) {instance = new SingletonLazy();}}}return instance;}// 构造方法同样也是 private 的private SingletonLazy() {}
}public class Demo19 {public static void main(String[] args) {Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();}
}

image.png
image.png

外层 if 为了降低加锁的频率 , 降低锁冲突的概率 . 里层 if 才是真正判定是否要实例化
我们再举个栗子帮大家理清楚为什么要用双层判断
image.png
其中 , 一个线程读 , 一个线程写还存在内存可见性问题
image.png

// 单例模式的实现
// 懒汉模式
class SingletonLazy {// 先不着急实例化volatile private static SingletonLazy instance = null;public static SingletonLazy getInstance() {// 进行判断// 为空->创建实例if(instance == null) {synchronized (SingletonLazy.class) {if(instance == null) {instance = new SingletonLazy();}}}return instance;}// 构造方法同样也是 private 的private SingletonLazy() {}
}public class Demo19 {public static void main(String[] args) {Singleton instance1 = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();}
}

image.png

对于 volatile , 有一种大家认同比较多的说法是这样
volatile 在此处的用途 , 是禁止指令重排序
image.png


关于这里 , 还有可能问到对象存储在哪里的问题 , 我们也需要格外关注一下
image.png

单例模式的分析就到这里了 , 觉得有收获的请一键三连嗷~
在这里插入图片描述

相关文章:

Java Web 实战 07 - 多线程基础之单例模式

大家好 , 这篇文章给大家带来的是单例模式 , 单例模式中分为懒汉模式和饿汉模式 , 懒汉模式是需要用的到的时候才去创建实例 , 而饿汉模式是程序一启动就立刻创建实例 , 在这其中还有很多其他问题需要我们去研究 推荐大家跳转到这里 , 观看效果更加 上一篇文章的链接我也贴在这…...

uniapp上实现左右关联滚动

先看效果&#xff1a; 代码&#xff1a; <template><view class"container"><!-- 左侧fixed导航区域 --><view class"left"><viewv-for"item in leftList":key"item.id"class"left_item":class…...

Docker Remote API未授权访问

目录Docker简述Docker 2375端口安全风险Docker命令连接利用声明&#xff1a;本文仅供学习参考&#xff0c;其中涉及的一切资源均来源于网络&#xff0c;请勿用于任何非法行为&#xff0c;否则您将自行承担相应后果&#xff0c;本人不承担任何法律及连带责任。Docker简述 Docke…...

【蓝桥杯】第十四届蓝桥杯模拟赛(第三期)C++ (弱go的记录,有问题的话求指点)

博主是菜鸡啦&#xff0c;代码仅供参考&#xff0c;只确定能过样例&#xff0c;嘻嘻~第一题&#xff0c;填空题问题描述请找到一个大于 2022 的最小数&#xff0c;这个数转换成十六进制之后&#xff0c;所有的数位&#xff08;不含前导 0&#xff09;都为字母&#xff08;A 到 …...

算法24:LeetCode_并查集相关算法

目录 题目一&#xff1a;力扣547题&#xff0c;求省份数量 题目二&#xff1a;岛屿数量 题目三&#xff1a;岛屿数量拓展 什么是并查集&#xff0c;举个简单的例子。学生考试通常会以60分为及格分数&#xff0c;我们将60分及以上的人归类为及格学生&#xff0c;而60分以下归…...

TypeScript核心知识点

TypeScript 核心 类型注解 知道&#xff1a;TypeScript 类型注解 示例代码&#xff1a; // 约定变量 age 的类型为 number 类型 let age: number 18 age 19: number 就是类型注解&#xff0c;它为变量提供类型约束。约定了什么类型&#xff0c;就只能给该变量赋值什么类型的…...

基于“遥感+”融合技术在碳储量、碳收支、碳循环等多领域监测与模拟实践

以全球变暖为主要特征的气候变化已成为全球性环境问题&#xff0c;对全球可持续发展带来严峻挑战。2015年多国在《巴黎协定》上明确提出缔约方应尽快实现碳达峰和碳中和目标。2019年第49届 IPCC全会明确增加了基于卫星遥感的排放清单校验方法。随着碳中和目标以及全球碳盘点的现…...

外卖点餐系统小程序 PHP+UniAPP

一、介绍 本项目是给某大学餐厅开发的外面点餐系统&#xff0c;该项目针对校内的学生&#xff0c;配送由学校的学生负责配送。因此&#xff0c;该项目不同于互联网的外卖点餐系统。 该系统支持属于 Saas 系统&#xff0c;由平台端、商家端、用户端、以及配送端组成。 其中&a…...

vuex3的介绍与state、actions和mutations的使用

一、定义官网&#xff1a;Vuex 是什么&#xff1f; | Vuex (vuejs.org)Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。二、安装cdn<script src"/path/…...

windows 自带端口转发

使用Portproxy模式下的Netsh命令即能实现Windows系统中的端口转发&#xff0c;转发命令如下: netsh interface portproxy add v4tov4 listenaddress[localaddress] listenport[localport] connectaddress[destaddress]listenaddress – 等待连接的本地ip地址 listenport – 本…...

【算法】算法基础入门详解:轻松理解和运用基础算法

&#x1f600;大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#x1f62b;&#xff0c;但是也想日更的人✈。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4…...

2.9.1 Packet Tracer - Basic Switch and End Device Configuration(作业)

Packet Tracer - 交换机和终端设备的基本 配置地址分配表目标使用命令行界面 (CLI)&#xff0c;在两台思科互联网络 操作系统 (IOS) 交换机上配置主机名和 IP 地址。使用思科 IOS 命令指定或限制对设备 配置的访问。使用 IOS 命令来保存当前的运行配置。配置两台主机设备的 IP …...

AtCoder Beginner Contest 216(F)

F - Max Sum Counting 链接&#xff1a; F - Max Sum Counting 题意 两个 大小为 nnn 的序列 aiaiai 和 bibibi&#xff0c;任意选取一些下标 iii&#xff0c;求 max⁡(ai)>∑bi\max(ai) > \sum{bi}max(ai)>∑bi的方案数。 解析 首先考虑状态 一是和&#xff0c;…...

每天学一点之Stream流相关操作

StreamAPI 一、Stream特点 Stream是数据渠道&#xff0c;用于操作数据源&#xff08;集合、数组等&#xff09;所生成的元素序列。“集合讲的是数据&#xff0c;负责存储数据&#xff0c;Stream流讲的是计算&#xff0c;负责处理数据&#xff01;” 注意&#xff1a; ①Str…...

MatCap模拟光照效果实现

大家好&#xff0c;我是阿赵 之前介绍过各种光照模型的实现方法。那些光照模型的实现虽然有算法上的不同&#xff0c;但基本上都是灯光方向和法线方向的计算得出的明暗结果。 下面介绍一种叫做MatCap的模拟光照效果&#xff0c;这种方式计算非常简单&#xff0c;脱离灯光的计算…...

二十一、PG管理

一、 PG异常状态说明 1、 PG状态介绍 可以通过ceph pg stat命令查看PG当前状态&#xff0c;健康状态为“active clean” [rootrbd01 ~]# ceph pg stat 192 pgs: 192 activeclean; 1.3 KiB data, 64 MiB used, 114 GiB / 120 GiB avail; 85 B/s rd, 0 op/s2、pg常见状态 状…...

SAPUI5开发01_01-Installing Eclipse

1.0 简要要求概述: 本节您将安装SAPUI 5,以及如何在Eclipse Juno中集成SAPUI 5工具。 1.1 安装JDK JDK 是一种用于构建在 Java 平台上发布的应用程序、Applet 和组件的开发环境,即编写 Java 程序必须使用 JDK,它提供了编译和运行 Java 程序的环境。 在安装 JDK 之前,首…...

Qt之高仿QQ系统设置界面

QQ或360安全卫士的设置界面都是非常有特点的,所有的配置项都在一个垂直的ScrollArea中,但是又能通过左侧的导航栏点击定位。这样做的好处是既方便查看指定配置项,又方便查看所有配置项。 一.效果 下面左边是当前最新版QQ的系统设置界面,右边是我的高仿版本,几乎一毛一样…...

JVM概览:内存空间与数据存储

核心的五个部分虚拟机栈&#xff1a;局部变量中基础类型数据、对象的引用存储的位置&#xff0c;线程独立的。堆&#xff1a;大量运行时对象都在这个区域存储&#xff0c;线程共享的。方法区&#xff1a;存储运行时代码、类变量、常量池、构造器等信息&#xff0c;线程共享。程…...

固态存储设备固件升级方案

1. 前言 随着数字化时代的发展&#xff0c;数字数据的量越来越大&#xff0c;相应的数据存储的需求也越来越大&#xff0c;存储设备产业也是蓬勃发展。存储设备产业中&#xff0c;发展最为迅猛的则是固态存储(Solid State Storage&#xff0c;SSS)。数字化时代&#xff0c;海量…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

React hook之useRef

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

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...