【JavaEE】单例模式

作者主页:paper jie_博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将MySQL基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《MySQL》《C语言》《javaSE》《数据结构》等

内容分享:本期将会分享设计模式中的单例模式

目录

什么是设计模式

什么是单例模式

单例模式的实现方式

饿汉模式

具体代码

代码分解 

懒汉模式

懒汉模式 - 单线程

具体代码

代码分析

懒汉模式 - 多线程

问题一: 原子性

改进

问题二: 加锁带来的开销

改进

问题三: 指令重排序

改进:


什么是设计模式

设计模式是咱们程序猿圈子中的一些大佬写出来的,为了规范我们的代码,让我们的代码不至于写的见不得人,可以说使用设计模式就等于给了你一个下限,只要你按照这个模式来写,再怎么样也不至于水到哪去. 就可以把它理解为好比棋谱一般.给了我们一些套路,在遇到什么情况,该什么应对. 我们软件开发中就是有许多常见的问题场景,针对这些问题场景,大佬们就总结出来一些固定的套路给我们这些小萌新使用.

什么是单例模式

单例模式它就是能保证某个类只能创建一个实例,而不能创建多个实例.这一点在很多场景中都需要使用.因为往往这类实例需要的内存空间和开销都比较大,我们就需要限制住创建实例的个数.

单例模式的实现方式

单例模式有许多种实现的方式,不过其中最常见的就是饿汉模式和懒汉模式.

饿汉模式

饿汉模式,顾名思义,对于创建这个实例非常迫切,在类一加载就创建好了.

具体代码

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

代码分解 

1. 这里的instance是静态属性,类属性. 是随着类的加载而创建.因为一个类只有一个类对象,类属性也只有一份,所以这里只能创建一次实例.

2. 在类外需要获取这个实例需要使用getinstance方法来获取,而不是自己再new一个.

3. 这里在类外再new一个对象会发现编译报错,这是因为这里将它的构造方法设置为私有的,在类外是访问不到.这就保证了只能创建一份实例.

懒汉模式

这里懒汉模式有两种,一种单线程,一种多线程.

懒汉模式 - 单线程

具体代码
class Singleton2 {private static Singleton2 instance = null;public Singleton2 getInstance() {if(instance == null) {return new Singleton2();}return instance;}private Singleton2() {}
}
代码分析

这里不会在类加载的时候直接创建实例,而是将创建实例放到了方法中. 当第一个调用getinstance方法时就会创建出实例.后面再使用这个方法时因为instance不是null后就不会再创建了.

这样的代码也可以保证只创建一次实例. 创建实例的实例就看代码中什么时候使用这个方法.这样创建实例就不是很急迫,只有需要的时候才会创建,所以叫懒汉. 且这样有一个好处就是如果用不到这个实例它就不会创建,遮掩就省了一笔开销.要知道一般单例模式中的实例都需要占很大的内存空间的,加载的时间需要很久,这样子加载的时间省了,空间也省了.

懒汉模式 - 多线程

在上述的单线程中,是没有多线程安全问题的,但是当在多线程协调工作时就会线程不安全.像饿汉模式也是线程安全的,因为它只涉及到读操作,但是懒汉模式涉及到读和写操作.这样就会有线程安全问题.

问题一: 原子性

我们假设有两个线程,t1和t2.它们都需要使用getinstance这样方法. 这里可能就会有一种情况: t1先执行,到t1执行到if()语句判断后它就被调度走了,这时t2调度过来执行.等t2执行完到new一个实例返回后,t1再执行.但是t1执行的时候它还是认为instance是null,于是它就又创建了一个实例.

这里就是因为这些操作没有具有原子性(当然这里是伪原子,只是针对t2这个线程来说)

改进

我们这里就需要用到我们的加锁操作了.将相关代码加锁!

class Singleton1 {private static Singleton1 instance = null;public Singleton1 getInstance() {synchronized (Singleton1.class) {if (instance == null) {return new Singleton1();}return instance;}}private Singleton1() {}
}
问题二: 加锁带来的开销

这里看似处理了问题,但是还有其他的毛病.这里我们发现加锁操作其实只有第一次创建对象(也就是改操作)是需要的,后面的操作都不需要,但是我们还是需要进行锁竞争,这里就是导致开销比较大.

改进

这里我们在外头再加上一层if判断即可. 这里的第一个if就是判断需不需要加锁,第二个if就是在加锁操作下判断有没有创建实例.

class Singleton1 {private static Singleton1 instance = null;public Singleton1 getInstance() {if(instance == null) {synchronized (Singleton1.class) {if(instance == null) {return new Singleton1();}}}return instance;}private Singleton1() {}
}
问题三: 指令重排序

对于new这个代码,有三个操作: 1. 申请一块内存. 2. 在这块内存中调用构造方法来初始化这个实例. 3. 将这个内存地址赋值到instance中.  这里一般来说我们就是按顺序执行.但是JVM中可能就会给你优化,也就是指令重排序. 可能就会出现 1 3 2这种顺序. 这里就会发生问题: 

这里也假设有t1和t2, 当t1一直执行到new操作的3后,这时就被CPU调度走了,让t2进来执行代码.当t2执行到第一个if判断时,发现instance不为null,他就直接返回了.但是这里的instance是一块没有被初始化的空间地址,这就会导致t2接下来的逻辑发生问题.

改进:

这里我们就需要用到我们的volatile.它有两个作用:

1. 保证内存可见性. 它可以强制让JVM不进行代码优化,保证每次都到内存中读取变量.

2. 禁止指令重排序. 针对volatile修饰的这个变量的相关指令,JVM是不可以优化重排序的.

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/196042.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python容器——字典

Key——Value 键值对

科技云报道:AI+PaaS,中国云计算市场迎来新“变量”?

科技云报道原创。 没有小的市场,只有还没有被发现的大生意。 随着企业数字化转型的逐级深入,市场需求进一步向PaaS和SaaS层进发,使之成为公有云服务市场增长的主要动力。 根据IDC最新发布的报告显示,2022-2027五年间中国公有云…

初识计算机网络

网络通信基础 1. IP地址2.端口号3.认识协议3.1协议分层 4. 网络数据传输的基本流程4.1 五元组4.2封装和分用 1. IP地址 IP地址主要用于表示网络主机,其他网络设备的网络地址,IP地址用于定位主机的网络地址 比如:发送快递的时候,需要知道对象的收货地址,才能将包裹送到目的地. …

APISpace 实名认证(身份证二要素)接口案例代码

1.实名认证(身份证二要素)API APISpace 的 实名认证(身份证二要素API),核验身份证二要素(姓名和身份证号码)信息是否一致。 2.实名认证(身份证二要素)接口详情 2.1 接口…

外汇天眼:CySEC宣布与Titanedge Securities 达成90,000欧元的和解

塞浦路斯证券交易委员会(CySEC)12月1日宣布已经与塞浦路斯投资公司Titanedge Securities Ltd 达成了一项和解。 此次和解涉及可能违反了2017年《投资服务和活动以及受监管市场法》的情况。更具体地说,达成和解的调查涉及评估该公司在2017/565…

自动化测试的4大注意事项

自动化测试能够提高测试效率、覆盖率,降低测试成本和工作量,是软件开发中不可或缺的一部分。但前提是要确保自动化测试的有效性和可靠性,否则无效或错误的自动化测试,往往会对项目造成负面影响,如维护成本高、假阳性和…

高等职业学校新媒体营销实训室解决方案

背景 随着数字化时代的来临,新媒体营销成为企业推广和品牌建设的关键手段。为了培养高职学生在新媒体领域的实际操作能力,建立一套全面、系统的实训室方案至关重要。 目标 搭建高职新媒体营销实训室,旨在培养学生的实际操作能力&#xff0…

这些B端产品设计规范,你都知道吗?

设计规范虽然有其通用性,但因应对不同的业务环境和企业形态,其具体的运用可能会有所差异。对于新入行的B端设计师,各种B端组件可能会让他们感到困惑,不知在何种场景下应选择何种组件。这主要是因为我们在日常中学到的B端知识点多是…

人工智能与供应链行业融合:开启智能化供应链的新时代

随着人工智能技术的快速发展,供应链行业正迎来革命性变革。本文将探索人工智能在供应链管理中的应用领域,并分析其带来的益处和挑战,展望人工智能与供应链融合的未来发展趋势。 引言 供应链管理是企业运营中不可或缺的重要组成部分。它涵盖了…

用友NC word.docx接口存在任意文件读取漏洞

声明 本文仅用于技术交流,请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 一、产品介绍 用友 NC Cloud,大型企业数字化平台&#xff…

如何在Linux上搭建本地Docker Registry镜像仓库并实现公网访问

Linux 本地 Docker Registry本地镜像仓库远程连接 文章目录 Linux 本地 Docker Registry本地镜像仓库远程连接1. 部署Docker Registry2. 本地测试推送镜像3. Linux 安装cpolar4. 配置Docker Registry公网访问地址5. 公网远程推送Docker Registry6. 固定Docker Registry公网地址…

地方公派|商学院老师对口加拿大古德曼商学院访学交流

L老师荣幸地入选某省中青年教师国外访学进修计划,但因DIY申请职位无果,求助于我们。最终我们克服干扰因素,为其对口落实了加拿大最具声望和影响力的商学院之一布鲁克大学-古德曼商学院(Goodman School of Business)。 …

本地存储与复杂数据类型转换

1. 本地存储介绍 2.1 本地存储分类 - localStorage // 存储一个名字localStorage.setItem(uname, abc)// 获取名字console.log(localStorage.getItem(uname));// 删除本地存储 只删名字// localStorage.removeItem(uname)// 改localStorage.setItem(uname, aaa)// 存一个年龄 …

怎么翻译英文医学文献资料

文献翻译是一项要求严谨、精确且地道的工作,对于医学文献翻译更是如此。那么,怎么翻译英文医学文献资料,医学英文文献翻译公司哪个好? 专业人士指出,在翻译医学文献时,理解原文的语境是至关重要的。这不仅需…

【改进YOLOV8】融合动态蛇形卷积&DCNV2的草莓分级分割分割系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着计算机视觉技术的不断发展,图像分割成为了一个重要的研究领域。图像分割可以将图像中的不同对象或区域进行分离,从而更好地理解图像内…

【数据结构(六)】排序算法介绍和算法的复杂度计算(1)

文章目录 1. 排序算法的介绍1.1. 排序的分类 2. 算法的时间复杂度2.1. 度量一个程序(算法)执行时间的两种方法2.2. 时间频度2.2.1. 忽略常数项2.2.2. 忽略低次项2.2.2. 忽略系数 2.3. 时间复杂度2.4. 常见的时间复杂度2.5. 平均时间复杂度和最坏时间复杂度 3. 算法的空间复杂度…

测试用例:微信发红包测试用例(最新版)

测试核心(重点): 功能界面安全性易用性兼容性性能 一、功能测试 1、一对一红包: 一对一发出去的红包自己不能领取。 一对一红包金额:最多200。 2、群发红包: (1)拼手气红包&#xff…

(03)vite 处理 css

文章目录 系列全集vite 处理css流程vite如何解决协同开发,样式重复覆盖的问题?使用less通过配置,更改vite的css默认行为 系列全集 (01)vite 从启动服务器开始 (02)vite环境变量配置 &#xff…

微服务调用组件Feign

JAVA 项目中如何实现接口调用? 1)Httpclient HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富 的支持 Http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传…

中国信通院公布2023下半年“可信数据库”测试结果

什么是可信数据库?定义具有强制和自主访问控制、审计、数据完整性、身份识别和鉴别、主客体分离等功能的数据库系统。是经过中国信通院评测的数据库产品及周边工具、数据库服务商和应用侧为评价目标的权威评测体系。 该体系包括基础能力、安全、性能、稳定性、服务商…