手撕单例的 5 种写法!

单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。当然,它也是面试中的常客,尤其是某手面试中经常要求应聘者手撕,所以今天咱们就来盘盘它。

单例模式的实现方式有很多,如下图所示:
在这里插入图片描述
具体实现如下。

1.饿汉式模式

此在饿汉式单例模式中,实例在类加载时就被创建,这种方式的优点是实现简单,线程安全(因为类加载过程是线程安全的)。缺点是可能会导致实例过早创建,如果实例创建过程比较耗时或者占用大量资源,而在程序运行初期并不需要该实例,就会造成资源浪费。

public class Singleton {// 1.私有静态成员变量,在类加载时就创建实例private static Singleton instance = new Singleton();// 2.私有构造函数,防止外部通过构造函数创建实例private Singleton() {}// 3.公共静态方法,用于获取唯一的实例public static Singleton getInstance() {return instance;}
}

2.懒汉模式(非安全)

懒汉式单例模式在第一次调用 getInstance 方法时才创建实例,这样可以避免实例过早创建。但上述代码是非线程安全的,在多线程环境下,可能会出现多个线程同时进入 if 语句,导致创建多个实例的情况。

public class Singleton {// 1.私有静态成员变量,初始化为nullprivate static Singleton instance = null;// 2.私有构造函数,防止外部通过构造函数创建实例private Singleton() {}// 3.公共静态方法,用于获取唯一的实例public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

3.懒汉模式(安全效率低)

此版本的懒汉式单例模式通过在 getInstance 方法上添加 synchronized 关键字,使其成为线程安全的。但这种方式的缺点是每次调用 getInstance 时都需要获取锁,会导致性能下降,尤其是在高并发环境下。

public class Singleton {// 1.私有静态成员变量,初始化为nullprivate static Singleton instance = null;// 2.私有构造函数,防止外部通过构造函数创建实例private Singleton() {}// 3.公共静态方法,用于获取唯一的实例public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

4.双重检查锁模式

双重检查锁定模式在懒汉式基础上进行了优化,通过两次检查 instance 是否为 null,既保证了在第一次需要实例时创建实例,又在一定程度上避免了每次调用 getInstance 都获取锁的情况,提高了性能。不过,由于指令重排序等问题,可能会导致一些错误,因此需要在 instance 变量前添加 volatile 关键字来解决。

public class Singleton {// 1.私有静态成员变量,初始化为nullprivate volatile static Singleton instance = null;// 2.私有构造函数,防止外部通过构造函数创建实例private Singleton() {}// 3.公共静态方法,用于获取唯一的实例public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

5.静态内部类模式

这种方式利用了静态内部类的特性,当外部类被加载时,静态内部类不会被加载,只有当调用 getInstance 方法时,静态内部类才会被加载,此时才创建单例实例。这种实现方式既保证了线程安全,又避免了在不需要实例时过早创建实例,是一种比较常用的单例模式实现方式。

public class Singleton {// 1.私有构造函数,防止外部通过构造函数创建实例private Singleton() {}// 2.静态内部类,其中包含单例实例private static class SingletonHolder {private static final Singleton instance = new Singleton();}// 3.公共静态方法,用于获取唯一的实例public static Singleton getInstance() {return SingletonHolder.instance;}
}

小结

单例模式虽然实现方式有 5 种:饿汉模式、懒汉非安全模式、懒汉安全模式、双重效验锁模式、静态内部类模式,但它的写法基本都是以下三步:

定义私有构造方法(防止 new 多个实例)。
定义私有变量(承接单例对象)。
定义统一返回对象的方法。

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

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

相关文章

制作Windows11个人iso镜像的方法

一、前期准备 1.光盘刻录软件AnyBurn 2.对应Windows11版本的iso基础镜像(一定要对应,不然封装的iso镜像无法使用) Windows11最新版本24H2的iso镜像下载地址下载 Windows 11 此前版本下载地址官方网站不再提供,需要自行搜索下载 笔…

timesnet+timemixer时间序列预测模型

1.timesnet 原论文源码:https://github.com/thuml/Time-Series-Library?tabreadme-ov-file 时间序列分析被广泛应用于众多领域中,如天气预报中预测气象要素的未来变化、数据质控时填补缺失值、工业生产中监控设备状态、医疗诊断时分析心跳曲线等。 不…

Linux 35.6 + JetPack v5.1.4之RTP实时视频Python框架

Linux 35.6 JetPack v5.1.4之RTP实时视频Python框架 1. 源由2. 思路3. 方法论3.1 扩展思考 - 慎谋而后定3.2 扩展思考 - 拒绝拖延或犹豫3.3 扩展思考 - 哲学思考3.4 逻辑实操 - 方法论 4 准备5. 分析5.1 gst-launch-1.05.1.1 xvimagesink5.1.2 nv3dsink5.1.3 nv3dsink sync05…

异或和公式

前缀异或和公式 前缀异或和的概念与前缀和类似,但它使用的是异或(XOR)操作而不是加法。异或操作有一些独特的性质,使得前缀异或和在处理某些问题时非常有用。下面是前缀异或和的推导原理: • 异或操作的性质&#xf…

【Unity】 HTFramework框架(五十三)使用 Addressables 可寻址系统

更新日期:2024年7月25日。 Github源码:[点我获取源码] Gitee源码:[点我获取源码] 索引 Addressables 可寻址系统使用 Addressables 可寻址系统一、导入 Addressables二、切换到 Addressables 加载模式三、切换资源加载助手四、加载资源五、注…

Spring Cache简单使用

Spring Cache是一个框架,实现了基于注解的缓存功能。只需要简单地加一个注解,就能实现缓存功能 Spring Cache提供了一层抽象,底层可以切换不同的缓存实现,例如: 1.EHCahce 2.Chffeine 3.Redis 需要导入的maven坐标 …

Delphi Web前端开发教程(9):基于TMS WEB Core框架

3、REST Servers服务端(后端)框架 REST服务端特点: – 为远程资源提供一个REST API接口。也可以为其他网络内容提供服务; – 包括在Delphi Enterprise & Architect企业版和架构师版中的RAD服务器、DataSnap、WebBroker; – 开源框架&a…

vue+mars3d点击图层展示炫酷的popup弹窗

展示效果 目录 一:叠加数据图层到地图上,此时需要使用bindPopup绑定popup 二、封装自定义的popup,样式可以自行调整 一:叠加数据图层到地图上,此时需要使用bindPopup绑定popup 这里我根据数据不同,展示的…

【机器人学】3-1.六自由度机器人速度域-雅克比矩阵【附MATLAB代码】

MATLAB仿真验证 已知六轴机器人的D-H参数如下所示: 关节1关节2关节3关节4关节5关节609000-9090a0042539300d160.700113.39993.60900-9000000000 通过D-H参数,选用改进型的D-H参数,可以得到各个关节间的旋转矩阵。详细请看我的第一篇博客六自…

基于SSM的网上拍卖系统+LW示例参考

1.项目介绍 系统角色:管理员、卖家、买家功能模块:用户管理、卖家管理、公告管理、竞拍物品管理、预约竞拍管理、竞拍管理等技术选型:SSM,jsp等测试环境:idea2024,jdk1.8,tomcat8,n…

Vue3安装 运行教程

本文是综合了所有vue安装教程而成 更细化 更简略 希望对各位读者有所帮助! Vue安装 1. Vue-cli脚手架安装 安装vue的方式有很多 我们这里选择npm方式安装vue npm方式 npm方式安装vue,详细介绍见下文。 1.node.js安装和配置 安装npm 需要安装note.js&…

帝可得-设备管理

设备管理 需求说明 点位管理主要涉及到三个功能模块,业务流程如下: 新增设备类型: 允许管理员定义新的售货机型号,包括其规格和容量。新增设备: 在新的设备类型定义后,系统应允许添加新的售货机实例,并将它们分配到特…

w070基于springboot的大创管理系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文件&#xff0…

FlyHttp 的最佳实践:加速项目级 API 请求构建

FlyHttp的相关文章: FlyHttp 的诞生:从认识各种网络请求开始 FlyHttp 的设计思想:前端 API 自动化构建工具 FlyHttp 的使用:如何高效使用 FlyHttp,支持 JS、TS 项目 一. FlyHttp 是什么? 这是一个自动…

七次课掌握 Photoshop:样式与滤镜

Photoshop 中的图层样式和滤镜功能,能够为图像添加丰富的效果和质感,使图像更加生动和富有创意。熟练掌握这些工具和方法,可以大大提升作品的视觉表现力。 一、图层样式 图层样式 Layer Styles是应用于图层或图层组的特效,如投影、…

ML23_变分推理Variational inference

可以先看第一期https://blog.csdn.net/qq_51605551/article/details/141901941 变分推理(Variational Inference, VI)是一种用于近似贝叶斯推断的方法,它在处理复杂的概率模型时特别有用。贝叶斯推断的核心是计算后验分布,即在给…

Map和Set(下)

我们先对上一小节部分进行一些复习和补充 1. 补充和强调 补充 1. HashMap 和 HashSet 即 java 中利用哈希表实现的 Map 和 Set 2. java 中使用的是哈希桶方式解决冲突的 3. java 会在冲突链表长度大于一定阈值后,将链表转变为搜索树(红黑树)条…

StackWalker 遍历栈帧

StackWalker 遍历栈帧 背景StackWalkerStackFrameOption方法创建 StackWalkerwalk例:打印所有信息例:打印反射帧、隐藏帧 forEachgetCallerClass例:直接调用、反射调用例:栈底调用会抛异常 参考 背景 在看 springboot 3.x 源码时…

捷联惯导原理和算法预备知识

原理和算法预备知识 牛顿第一运动定律-惯性定律:如一物体不受外力作用,它将保持静止状态或匀速直线运动状态不变。 牛顿第二运动定律:表达式为Fma,。其中F为物体所受的合力,m为物体的质量,a为物体的加速度。这个公式…

便捷工具--ssh登录ubuntu

一、概述 由于ubuntu终端的使用会有诸多不便捷的地方,建议使用mobaterm、xshell、SecureCRT等软件,通过ssh方式,操作虚拟机的ubuntu系统。 1、ssh的安装 sudo apt install openssh-server2、查看ubuntu的ip 3、ssh端登录 ssh链接linux端的…