用简单易懂的方式手写一个单例模式,看了不会来打我

news2024/12/26 23:50:46

文章目录

  • 一、如何手写一个单例模式
    • 1.1 什么是单例模式
    • 1.2 单例模式的适用场景
    • 1.3 单例模式的设计原理
    • 1.4 单例模式的实现方案
    • 1.5 代码测试

一、如何手写一个单例模式

1.1 什么是单例模式

单例模式是一种常用的软件设计模式,它的核心是只包含一个实例的特殊类。单例模式可以保证系统中一个类只有一个实例,对实例个数进行控制可以节约节省内存,加快对象的访问速度。

1.2 单例模式的适用场景

资源共享:当系统中需要共享某个资源,并且该资源只能被一个对象访问和修改时,可以使用单例模式。例如,一个数据库连接池,多个线程需要访问数据库连接,但是连接数量有限,此时可以使用单例模式确保只有一个连接池对象。

对象控制:在某些情况下,系统需要限制某个类只能拥有一个实例。例如,一个系统中只能有一个配置文件读取对象,以确保配置信息的一致性和避免重复读取。

日志记录器:在日志记录器中,由于多个对象可能同时需要写入日志,为了避免产生混乱的日志信息,可以使用单例模式。单例模式可以确保只有一个日志记录器实例存在,并且所有对象共享同一个实例进行日志记录。

缓存、对话框框架等:在一些需要频繁创建和销毁对象的场景中,为了提高性能,可以使用单例模式来管理对象的生命周期和减少资源消耗。

1.3 单例模式的设计原理

将构造函数设置为 private,避免外部通过 new 创建实例,创建一个静态方法返回单例类对象 ,同时需要考虑对象创建时的线程安全问题,确保单例类的对象 有且仅有一个 ,尤其是在多线程环境下, 确保单例类对象在反序列化时不会重新构建对象。

1.4 单例模式的实现方案

  1. 创建一个 Siglegle 类,类中有一个本类的实例成员属性,该实例使用 static(原因看第 3 点) 和 volatile 进行修饰,volatile 是避免出现指令重排。因为如果指令重排线程 1 在创建实例的时候可能会先分配内存和指向分配再进行初始化,而线程 2 可能在线程 1 执行到初始化之前就对实例对象进行判断是否为空,因为分配了指向此时是不为空的,那么线程 2 可能就会返回一个还未初始化的实例;
  2. 编写构造函数,将 private 作为构造函数的访问修饰符,构造函数内部打印一句话是为了判断调用了几次构造函数;
  3. 编写一个静态方法用于对象实例的创建,因为第一次创建之前是没有实例的,如果不是静态方法就无法进行访问,因为静态方法只能访问静态成员故 siglegle 对象也需要是静态的。
  4. 在创建之前先判断是否为空,如果为空就进行创建;
  5. 在对象加锁避免两个线程同时运行;
  6. 这里很多人搞不清楚为什么有第二次 if 判断,其实很简单,假设线程 1 使用了锁但还未创建对象,同时线程 2 判断实例为空也进行对锁的申请,而等线程 1 创建完对象之后放弃锁的使用权,这时候线程 2 获得了锁的使用权,又进行一次对象的创建,此时就会出现两个实例,破坏了单例模式;
  7. 最后返回 siglegle 对象;
public class Siglegle {
	private static volatile Siglegle siglegle;
	private Siglegle() {
		// TODO Auto-generated constructor stub
		System.out.println("创建了一个实例");
	}
	public static Siglegle createSiglegle() {
		if(siglegle == null)
			synchronized(Siglegle.class) {
				if (siglegle == null) 
					siglegle = new Siglegle();
			}
		return siglegle;
	}
}

1.5 代码测试

测试规则:创建两个线程,每个线程调用 10 次 Siglegle 的创建对象方法,最后通过控制台的输出条数来判断共调用了多少次构造方法;

测试代码

public class TestCreate {
	public static void main(String[] args) {
		Thread thread1 = new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for (int i = 0; i < 10; i++)
					Siglegle.createSiglegle();
			}
		});
		Thread thread2 = new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for (int i = 0; i < 10; i++)
					Siglegle.createSiglegle();
			}
		});
		thread1.start();
		thread2.start();
	}
}

测试结果

在这里插入图片描述

测试分析:两个线程分别调用 10 次 Siglegle 的创建对象方法,执行完毕后控制台共出现 1 条输出,即 Siglegle 的构造方法只被调用了一次,本次测试对象无错误可使用;

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

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

相关文章

每日一道算法题--进制转换

进制转换 题目来源解题思路代码 题目来源 题目链接: 进制转换 解题思路 首先&#xff0c;从标准输入读取两个整数 M 和 N&#xff0c;分别表示待转换的十进制数和目标进制。如果输入的十进制数 M 等于 0&#xff0c;直接输出 0 并返回。判断输入的十进制数是否为负数&#xf…

网络商城源码如何选择?

电商行业的不断发展&#xff0c;越来越多的企业和商家希望建设自己的网络商城系统&#xff0c;为消费者提供更加便捷的购物体验。 但是&#xff0c;想要实现这一目标&#xff0c;选择一款优秀的网络商城系统源码至关重要。那么&#xff0c;在如此众多的商城系统源码中&#xff…

局域网内,将笔记本作为台式机的扩展屏

目录 1、驱动端下载&#xff1a; 2、笔记本下载 显示端&#xff1a; 3、连接状态&#xff1a; 4、笔记本扩展屏&#xff1a; 如果&#xff0c;都支持无线显示器的话&#xff0c;可以用window内置的winp实现&#xff0c;可惜我的台式机不支持&#xff0c;所以采用了软件的方…

结构体和数据结构--向函数传递结构体

将结构体传给函数的方式有以下三种&#xff1a; 目录 一、用结构体的单个成员作为函数参数&#xff0c;向函数传递结构体的单个成员 二、用结构体变量作函数实参&#xff0c;向函数传递结构体得完整结构 三、用结构体指针或结构体数组作函数参数&#xff0c;向函数传递结构体…

亿发软件:智能制造时代,企业为什么选择量身定制信息化软件系统

在快节奏的市场环境中&#xff0c;每个企业都寻求建立自己的管理模式&#xff0c;这往往成为竞争优势。然而&#xff0c;标准化软件产品的使用有时会扼杀企业管理的个性化&#xff0c;而僵化的制度则阻碍管理升级。此外&#xff0c;单个的部门级软件会造成信息孤岛&#xff0c;…

【电子量产工具】2.输入系统

文章目录 前言一、输入系统分析二、封装输入结构体三、底层 touchscreen四、底层 netinput五、显示管理层六、测试程序测试效果 总结 前言 最近看了 电子量产工具 这个项目&#xff0c;本专栏是对该项目的一个总结。 对于输入系统&#xff0c;这里只介绍 触摸屏线程 和 网络线…

7-WebApis-6

Web APIs - 6 目标&#xff1a;能够利用正则表达式完成小兔鲜注册页面的表单验证&#xff0c;具备常见的表单验证能力 正则表达式综合案例阶段案例 正则表达式 正则表达式&#xff08;Regular Expression是一种字符串匹配的模式&#xff08;规则&#xff09; 使用场景&#…

微信小程序申请

方案说明&#xff1a; 微信小程序申请步骤有两个过程&#xff0c;目前采用的是第二种方案 第一种方案&#xff1a;直接向微信申请微信小程序 第二种方案&#xff1a;先申请公众号后再通过公众号快速注册并申请小程序 无论申请公众号还是小程序都需要微信认证&#xff0c;微…

ubuntu18.04下安装PCL

整体步骤可参考&#xff1a;https://blog.csdn.net/qq_42257666/article/details/124574029 在本人安装过程中&#xff0c;遇到一些问题&#xff0c;做几点说明&#xff1a; 1.在配置VTK的过程中报错如下&#xff1a; 解决方法&#xff1a; sudo apt install libqt5x11extras…

Nginx【Nginx核心指令(rewrite指令、实战rewrite 、if指令、set和break指令】(六)-全面详解(学习总结---从入门到深化)

目录 Nginx核心指令_rewrite指令 Nginx核心指令_实战rewrite Nginx核心指令_if指令 Nginx核心指令_set和break指令 Nginx核心指令_rewrite指令 地址重写与地址转发 地址重写 地址重写是实际上是为了实现址标准化&#xff0c;就像访问www.baidu.cn可 以出现www.baidu.com的…

阿里云企业邮箱标准版用户数功能说明

阿里云企业邮箱标准版不同用户数费用表&#xff0c;标准版企业邮箱不限制账号容量、20GB共享网盘容量、5GB个人网盘容量&#xff0c;默认5个账号数540元一年&#xff0c;原价是600元一年&#xff0c;年付9折、多年付8折&#xff0c;阿里云百科分享企业邮箱标准版不同账号数收费…

软件测试技能,JMeter压力测试教程,请求body自动签名带上sign参数(二十一)

一、前言 接口请求body带有sign签名参数&#xff0c;sign签名是根据请求body除去sign本身参数后&#xff0c;拼接请求参数最后md5加密生成的 使用 jmeter 测试接口&#xff0c;我们希望在请求之前修改 post body 里面的 sign 参数的值为签名的值 二、sign签名 签名一篇的实…

Alibaba Sentinel | 熔断规则详解

文章目录 简介熔断策略-慢调用比例结论&#xff1a;流程图&#xff1a;熔断结果详细解释 熔断策略-异常比例结论&#xff1a;详细解释 熔断策略-异常数结论&#xff1a;详细解释 统计异常数、比例的方法编码加注解RuntimeException 总结 简介 熔断是一种保护机制&#xff0c;用…

Redis持久化(RDB、AOF)

Redis持久化&#xff08;RDB、AOF&#xff09; 一、Redis高可用二、Redis持久化三、Redis的RDB持久化1、触发条件1.1 手动触发1.2 自动触发1.3 其它自动触发机制 2、执行流程3、启动时加载RED文件(恢复) 四、Redis的AOF持久化1、开启AOF2、执行流程2.1 命令追加&#xff08;app…

杂记:逆向一块FPGA核心板

最近太热了&#xff0c;实在无心看书。阵列书丢一边看不进去&#xff0c;还买了几本统计信号的甚至都没开始看&#xff08;笑&#xff09;&#xff0c;躺在床上玩玩手机摆烂&#xff0c;看到某黄色APP上有老板卖拆机的板子&#xff0c;价格美丽&#xff0c;美中不足的是没有资料…

JavaFX布局详解与代码实例

JavaFX布局详解与代码实例 一、JavaFX布局的原理1.1 JavaFX布局容器1.2 布局约束 二、常用JavaFX布局2.1 VBox和HBox布局2.2 GridPane布局2.3 BorderPane布局 三、JavaFX布局代码实例四、总结与展望 正文&#xff1a; 引言&#xff1a; JavaFX是一种功能强大的用户界面&#xf…

SFP6012-ASEMI代理MHCHXM(海矽美)二极管SFP6012

编辑&#xff1a;ll SFP6012-ASEMI代理MHCHXM&#xff08;海矽美&#xff09;二极管SFP6012 型号&#xff1a;SFP6012 品牌&#xff1a;MHCHXM&#xff08;海矽美&#xff09; 封装&#xff1a;TO-247AB 恢复时间&#xff1a;≤75ns 正向电流&#xff1a;30A 反向耐压&a…

Excel表格转换

原始数据 1部 2部 3部 4部 5部 6部 7部 8部 9部 郈思 王瑾 郈思 许嘉 郈思 施眉 郈思 王瑾 郈思 许嘉 郈思 许嘉 吕倩倩 孙帮菊 夏侯瑾 孙帮菊 吕倩倩 孙痴梦 孙帮菊 姜佳 王瑾 孙痴梦 王瑾 许嘉 施眉 施眉 杨婕 施眉 施眉 孙帮菊 杨孝洁 施眉 吕倩倩 孙痴梦 郈思 夏侯瑾 李文…

NR 吞吐量测试

前言 参考文档&#xff1a; 5G NR TBS (Transport Block size) Calculator | 5G-Tools.com 5G NR Transport Block Size (TBS) Calculation - Techplayon 5G MCS _ 搜索结果_哔哩哔哩_Bilibili 4/5G无线资源和数据调度流程:CQI上报、基站AMC调度、调度信息DCI下发、CQI到MCS的对…

网络控制地址转换管理技术

网络控制&地址转换&管理技术 一、网络控制技术ACL1.1、ACL应用场景1.2、ACL分类1.3、ACL规则1.4、基本ACL配置1.5、高级ACL配置1.6、总结 二、网络地址转换NAT2.1、NAT应用场景2.2、静态NAT2.3、静态NAT配置2.4、动态NAT2.5、动态NAT配置12.6、动态NAT配置22.7、NAPT2.…