网站群建设报价/kol推广是什么意思
大家好 , 这篇文章给大家带来的是单例模式 , 单例模式中分为懒汉模式和饿汉模式 , 懒汉模式是需要用的到的时候才去创建实例 , 而饿汉模式是程序一启动就立刻创建实例 , 在这其中还有很多其他问题需要我们去研究
推荐大家跳转到这里 , 观看效果更加
上一篇文章的链接我也贴在这里了
单例模式
- 单例模式
- 1. 饿汉模式 : 程序启动立即创建实例
- 2. 懒汉模式 : 程序启动先不创建实例 , 等到真正有用的时候再创建实例
- 3. 正题 : 上述的两个单例模式的代码在多线程环境下调用 getInstance() 是线程安全的吗?
单例模式
单例模式是一种非常常见的设计模式
设计模式就相当于棋谱 , 前人总结出的一些固定套路 , 如果我们按照这些固定套路 , 代码就不会写的太离谱
设计模式虽然很有用 , 但是需要大家有一定的编程经验才好理解一点
未来肯定会经常和设计模式打交道 , 但是现在我们还是学习一下面试中比较常见的设计模式
校招中 , 关于设计模式 , 主要考察两个 : 单例模式、工厂模式
单例模式的目的就是 : 有些对象 , 在一个程序中应该只有一个实例 , 就可以使用单例模式
在单例模式下 , 对象的实例化就被限制了 , 只能创建一个 , 多的就不能再创建了
单例模式就是借助相关语法强制限制咱们不能创建多个实例
开车为啥要系安全带 ?
大家都不想出现事故 , 但是通过司机并不能完全保证安全
所以就出现了安全带 , 一定程度上保证了安全
在 Java 中 , 单例模式有很多种实现方式
我们主要介绍两个 : 饿汉模式 和 懒汉模式
他们俩描述的是 创建实例的时机
饿汉模式 : 程序启动立即创建实例
懒汉模式 : 程序启动先不创建实例 , 等到真正有用的时候再创建实例
大家不要把懒理解成贬义词 , 在计算机中 , 懒这个字往往意味着性能比较高
许多科技的发明都是因为人类懒 , 想要方便生活
计算机中 , 这种思想很常见
硬盘里面有许多大文件
使用文件资源管理器打开它
- 饿汉模式 : 把这些大文件通通读到内存中 , 读取完毕之后再让用户进行查看和修改
- 懒汉模式 : 只读取出当前页面能显示出的范围的文件数目 , 随着用户翻页 , 继续再读后面内容 , 用户还没翻到 , 就不着急度
或者刷抖音 , 不是一下子加载出所有的视频 , 而是一个一个加载 , 刷完了再加载下一条
或者微信朋友圈 , 只有当你点进去的时候 , 才会加载原图 , 否则就不加载
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}
}
如果我们再手动创建一个实例 , 就会报错
单例模式的关键是 : 使用静态成员表示实例 (唯一性) + 让构造方法为私有 (堵住了 new 创建新实例的方式)
那么这段代码为什么说是饿汉模式呢 ?
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();}
}
3. 正题 : 上述的两个单例模式的代码在多线程环境下调用 getInstance() 是线程安全的吗?
饿汉模式是天然线程安全的
懒汉模式是线程不安全的
懒汉模式一旦实例创建好之后 , 后续 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();}
}
但是目前还是有问题
懒汉模式只是初始情况下 , 才会有线程不安全问题
一旦实例创建好了之后 , 此时就安全了
既然如此 , 后续再调用 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();}
}
外层 if 为了降低加锁的频率 , 降低锁冲突的概率 . 里层 if 才是真正判定是否要实例化
我们再举个栗子帮大家理清楚为什么要用双层判断
其中 , 一个线程读 , 一个线程写还存在内存可见性问题
// 单例模式的实现
// 懒汉模式
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();}
}
对于 volatile , 有一种大家认同比较多的说法是这样
volatile 在此处的用途 , 是禁止指令重排序
关于这里 , 还有可能问到对象存储在哪里的问题 , 我们也需要格外关注一下
单例模式的分析就到这里了 , 觉得有收获的请一键三连嗷~
相关文章:

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

uniapp上实现左右关联滚动
先看效果: 代码: <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命令连接利用声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。Docker简述 Docke…...

【蓝桥杯】第十四届蓝桥杯模拟赛(第三期)C++ (弱go的记录,有问题的话求指点)
博主是菜鸡啦,代码仅供参考,只确定能过样例,嘻嘻~第一题,填空题问题描述请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 …...

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

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

基于“遥感+”融合技术在碳储量、碳收支、碳循环等多领域监测与模拟实践
以全球变暖为主要特征的气候变化已成为全球性环境问题,对全球可持续发展带来严峻挑战。2015年多国在《巴黎协定》上明确提出缔约方应尽快实现碳达峰和碳中和目标。2019年第49届 IPCC全会明确增加了基于卫星遥感的排放清单校验方法。随着碳中和目标以及全球碳盘点的现…...

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

vuex3的介绍与state、actions和mutations的使用
一、定义官网:Vuex 是什么? | Vuex (vuejs.org)Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。二、安装cdn<script src"/path/…...

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

【算法】算法基础入门详解:轻松理解和运用基础算法
😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!Ǵ…...

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

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

每天学一点之Stream流相关操作
StreamAPI 一、Stream特点 Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,负责存储数据,Stream流讲的是计算,负责处理数据!” 注意: ①Str…...

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

二十一、PG管理
一、 PG异常状态说明 1、 PG状态介绍 可以通过ceph pg stat命令查看PG当前状态,健康状态为“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概览:内存空间与数据存储
核心的五个部分虚拟机栈:局部变量中基础类型数据、对象的引用存储的位置,线程独立的。堆:大量运行时对象都在这个区域存储,线程共享的。方法区:存储运行时代码、类变量、常量池、构造器等信息,线程共享。程…...

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

Python交通标志识别基于卷积神经网络的保姆级教程(Tensorflow)
项目介绍 TensorFlow2.X 搭建卷积神经网络(CNN),实现交通标志识别。搭建的卷积神经网络是类似VGG的结构(卷积层与池化层反复堆叠,然后经过全连接层,最后用softmax映射为每个类别的概率,概率最大的即为识别…...

基于Selenium+Python的web自动化测试框架(附框架源码+项目实战)
目录 一、什么是Selenium? 二、自动化测试框架 三、自动化框架的设计和实现 四、需要改进的模块 五、总结 总结感谢每一个认真阅读我文章的人!!! 重点:配套学习资料和视频教学 一、什么是Selenium? …...

Python进阶-----高阶函数zip() 函数
目录 前言: zip() 函数简介 运作过程: 应用实例 1.有序序列结合 2.无序序列结合 3.长度不统一的情况 前言: 家人们,看到标题应该都不陌生了吧,我们都知道压缩包文件的后缀就是zip的,当然还有r…...

win10打印机拒绝访问解决方法
一直以来,在安装使用共享打印机打印一些文件的时候,会遇到错误提示:“无法访问.你可能没有权限使用网络资源。请与这台服务器的管理员联系”的问题,那为什么共享打印机拒绝访问呢?别着急,下面为大家带来相关的解决方法…...

深度学习训练营之数据增强
深度学习训练营学习内容原文链接环境介绍前置工作设置GPU加载数据创建测试集数据类型查看以及数据归一化数据增强操作使用嵌入model的方法进行数据增强模型训练结果可视化自定义数据增强查看数据增强后的图片学习内容 在深度学习当中,由于准备数据集本身是一件十分复杂的过程,…...

Tomcat安装及启动
日升时奋斗,日落时自省 目录 1、Tomcat下载 2、JDK安装及配置环境 3、Tomcat配置环境 4、启动Tomcat 5、部署演示 1、Tomcat下载 直接入主题,下载Tomcat 首先就是别下错了,直接找官方如何看是不是广告,或者造假 搜索Tomc…...

【专项训练】排序算法
排序算法 非比较类的排序,基本上就是放在一个数组里面,统计每个数出现的次序 最重要的排序是比较类排序! O(nlogn)的3个排序,必须要会!即:堆排序、快速排序、归并排序! 快速排序:分治 经典快排 def quickSort1(arr...

Android压测测试事件行为参数对照表
执行参数参数说明颗粒度指标基础参数--throttle <ms> 用于指定用户操作间的时延。 -s 随机数种子,用于指定伪随机数生成器的seed值,如果seed值相同,则产生的时间序列也相同。多用于重测、复现问题。 -v 指定输出日志的级别,…...

【观察】亚信科技:“飞轮效应”背后的数智化创新“延长线”
著名管理学家吉姆柯林斯在《从优秀到卓越》一书中提出“飞轮效应”,它指的是为了使静止的飞轮转动起来,一开始必须使很大的力气,每转一圈都很费力,但达到某一临界点后,飞轮的重力和冲力就会成为推动力的一部分…...

QT编程从入门到精通之十四:“第五章:Qt GUI应用程序设计”之“5.1 UI文件设计与运行机制”之“5.1.1 项目文件组成”
目录 第五章:Qt GUI应用程序设计 5.1 UI文件设计与运行机制 5.1.1 项目文件组成 第五章:Qt GUI应用程序设计...