【设计者模式】单例模式
文章目录
- 1、模式定义
- 2、代码实现
- (1)双重判空加锁方式
- 两次判空的作用?
- volatile 关键字的作用?
- 构造函数私有?
- (2)静态内部类【推荐】
- (3)Kotlin中的单例模式
- lateinit 和 by lazy 的区别:
- 3、优缺点
- 4、参考资料
1、模式定义
- 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
- 单例特别:(1)单例模式只能有一个实例。(2)单例类必须创建自己的唯一实例。(3)单例类必须向其他对象提供这一实例。
2、代码实现
(1)双重判空加锁方式
public class Singlnton{private static volatile Singlnton instance;private Singlnton(){}public static Singlnton getInstance(){ // 1if(instance==null){ // 2synchronized(Singlnton.class){ // 3if(instance==null){ // 4instance = new Singlnton(); // 5}}}return instance;}}
两次判空的作用?
- 第一次:避免加锁
- 第二次:进行实例化
volatile 关键字的作用?
- 双重检锁单例模式在 CPU 的工作流,主要分为三步,1:分配内存对象空间。2:初始化对象。3:设置 instance 执行刚才分配的内存地址。注意 JVM 和 CPU 优化会指令重排,上面顺序会变成 1 -> 3 -> 2,单线程环境下,此顺序是没有问题,2 和 3 前后没有依赖性,但是在多线程情况下会有这种情况,当线程 A 在执行第 5 行代码时,B 线程进来执行到第 2 行代码。假设此时 A 执行的过程中发生了指令重排序,即先执行了 1 和 3,没有执行 2。那么由于 A 线程执行了 3 导致 instance 指向了一段地址,所以 B 线程判断 instance 不为 null,会直接跳到第 6 行并返回一个未初始化的对象,此时会产生空指针异常。volatile 能保持指令的有序性,能够有效禁止指令重排序。
- 注意:“Singlnton instance” 相当于分配内存对象空间;“new Singlnton()” 相当于初始化对象;"="相当于设置 instance 执行刚才分配的内存地址。
构造函数私有?
- 无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法 getInstance 来得到该类的唯一实例
(2)静态内部类【推荐】
public class Singlnton{private Singlnton(){}private static class SinglntonHolder{private static Singlnton INSTANCE = new Singlnton();}public static Singlnton getInstance(){return SinglntonHolder.INSTANCE;}}
- 利用 JAVA 虚拟机加载类的特性实现延迟加载和线程安全
- 由于静态单例对象没有作为 Singleton 的成员变量直接实例化,因此类加载时不会实例化 Singleton,第一次调用 getInstance() 时将加载内部类 SingletonHolder,在该内部类中定义了一个 static 类型的变量 INSTANCE,此时会首先初始化这个成员变量,由 Java 虚拟机来保证其线程安全性,确保该成员变量只能初始化一次。由于 getInstance() 方法没有任何线程锁定,因此其性能不会造成任何影响。
- 类加载机制
(3)Kotlin中的单例模式
class Singlnton private constructor(){companion object{val instance : Singlnton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {Singlnton() }}}class Singlnton private constructor(){companion object{@Volatileprivate var instance: Singlnton? = nullfun getInstance(): Singlnton =instance ?: synchronized(this) {instance ?: Singlnton().also {instance = it}}}}
lateinit 和 by lazy 的区别:
- lateinit 只能用于修饰变量 var,不能用于可空的属性和 Java 的基本类型。
- lateinit 可以在任何位置初始化并且可以初始化多次。
- lazy() 只能用于修饰常量 val,并且 lazy() 是线程安全的。
- lazy() 是一个函数,可以接受一个 Lambda 表达式作为参数,第一次调用时会执行 Lambda 表达式,以后调用该属性会返回之前的结果。
- lazy() 源码分析
3、优缺点
- 优点:
- (1)在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
- (2)避免对资源的多重占用。
- 缺点:
- (1)没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
- (2)滥用单例会带来一些负面问题。如果实例化的对象长时间不被使用,系统会认定为垃圾而回收,这将导致共享对象状态的改变
- 注意事项:++不能使用反射调用私有构造器,这样会实例化一个新的对象++
- 如何避免反射创建新的单例对象
4、参考资料
- 单例模式 Android 校招面试指南(只能在手机端打开)
相关文章:
【设计者模式】单例模式
文章目录 1、模式定义2、代码实现(1)双重判空加锁方式两次判空的作用?volatile 关键字的作用?构造函数私有? (2)静态内部类【推荐】(3)Kotlin中的单例模式lateinit 和 by…...

Windows7缺失api-ms-win-crt-runtime-l1-1-0.dll的解决方法
api-ms-win-crt-runtime-l1-1-0.dll是一个在Windows操作系统环境下至关重要的动态链接库文件(DLL),它是Microsoft Visual C Redistributable的一部分,负责实现C运行时库的相关功能。这个特定的DLL文件提供了大量的底层运行支持&am…...

coqui-ai/TTS 安装使用
Coqui AI的TTS是一款开源深度学习文本转语音工具,以高质量、多语言合成著称。它提供超过1100种语言的预训练模型库,能够轻松集成到各种应用中,并允许用户通过简单API进行个性化声音训练与微调。其技术亮点包括但不限于低资源适应性࿰…...
Spring AOP相关注解及执行顺序
Aspect(切面):用于标识一个类是切面的注解。通常与其他通知注解一起使用,定义切面类。 Pointcut(切点): 注解来定义切点,它用于描述哪些连接点将会被通知所通知。 连接点ÿ…...
C++从零开始的打怪升级之路(day44)
这是关于一个普通双非本科大一学生的C的学习记录贴 在此前,我学了一点点C语言还有简单的数据结构,如果有小伙伴想和我一起学习的,可以私信我交流分享学习资料 那么开启正题 今天分享的是关于二叉搜索树的知识点 1.二叉搜索树概念 二叉搜…...
[C++核心编程](七):类和对象——运算符重载*
目录 四则运算符重载 左移运算符重载 递增运算符重载 赋值运算符重载 关系运算符重载 函数调用运算符重载 对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型 四则运算符重载 对自定义数据类型实现四则运算(加减乘除&…...
什么是MVC和MVVM
**MVC和MVVM是两种流行的软件架构模式,它们在前端开发中被广泛采用来组织代码和管理应用程序的复杂性**。具体如下: MVC(Model-View-Controller): 1. 模型(Model):负责管理数据和业…...

物体检测-系列教程23:YOLOV5 源码解析13 (SPP层、Flatten模块、Concat模块、Classify模块)
😎😎😎物体检测-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 17、SPP模块 17.1 SPP类 SPP是一种特殊的池化策略,最初在YOLOv3-SPP中被使用…...

2024.3.6每日一题
LeetCode 找出数组中的 K -or 值 题目链接:2917. 找出数组中的 K-or 值 - 力扣(LeetCode) 题目描述 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 nums 中的 K-or 是一个满足以下条件的非负整数: 只有在 nums 中&…...

YOLOSHOW - YOLOv5 / YOLOv7 / YOLOv8 / YOLOv9 基于 Pyside6 的图形化界面
YOLOSHOW 是一个基于 PySide6(Qt for Python)开发的图形化界面应用程序,主要用于集成和可视化YOLO系列(包括但不限于YOLOv5、YOLOv7、YOLOv8、YOLOv9)的目标检测模型。YOLOSHOW 提供了一个用户友好的交互界面ÿ…...

sql高级
sql高级 SQL SELECT TOP 子句 SELECT TOP 子句用于规定要返回的记录的数目。 SELECT TOP 子句对于拥有数千条记录的大型表来说,是非常有用的。 **注意:**并非所有的数据库系统都支持 SELECT TOP 语句。 MySQL 支持 LIMIT 语句来选取指定的条数数据, O…...

更快更强,Claude 3全面超越GPT4,能归纳15万单词
ChatGPT4和Gemini Ultra被Claude 3 AI模型超越了? 3月4日周一,人工智能公司Anthropic推出了Claude 3系列AI模型和新型聊天机器人,其中包括Opus、Sonnet和Haiku三种模型,该公司声称,这是迄今为止它们开发的最快速、最强…...
devc++小游戏3.8.5
导航: Dev-c跑酷小游戏 1.0.0 devc跑酷小游戏1.2.5 devc跑酷游戏1.2.6 devc跑酷游戏2.0.0 devc跑酷游戏2.0.1 devc跑酷游戏2.4.0 devc跑酷小游戏3.5.0 更新内容 重磅回归,存档搞定!!! 每一关需要前一关已…...

Java网络通信TCP
目录 TCP两个核心类 服务端 1.用ServerSocker类创建对象并且手动指定端口号 2.accept阻塞连接服务端与客户端 3.给客户端提供处理业务方法 4.处理业务 整体代码 客户端 1.创建Socket对象,并连接服务端的ip与端口号 2.获取Socket流对象,写入数据…...
层级锁笔记
注意看test_hierarchy_lock函数:如果thread t2的不注释,就会报错。 这是因为层级锁 更强调单个线程内上锁的顺序。 线程t2已经获取了hmtx2,再试图获取hmtx1就会因为违反层级顺序而抛出异常。 #include <mutex> #include <thread&g…...

基于SpringBoot+Vue 的专家医院预约挂号系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
计算机基础专升本笔记十二-Excel常用快捷键大全
计算机基础专升本笔记十二-Excel常用快捷键大全 Excel常用快捷键 按键作用Ctrl 0隐藏列Ctrl 1设置单元格格式Ctrl 2添加或取消字体加粗Ctrl 3添加或取消字体倾斜Ctrl 4添加或取消下划线Ctrl 5添加或取消删除线Ctrl 6隐藏或显示图形Ctrl 7隐藏工具栏Ctrl 8隐藏或显示…...

制作耳机壳的UV树脂和塑料材质相比优势有哪些?
制作耳机壳的UV树脂相比塑料材质有以下优势: 高强度与耐磨性:UV树脂具有高强度和耐磨性,能够更好地保护耳机内部零件,延长耳机使用寿命。相比之下,塑料材质可能较易磨损或刮伤。耐高温:UV树脂具有较好的耐…...

JS(JavaScript)中如何实现,复选框checkbox多选功能
起始界面: 代码元素: <p><input type"checkbox" id"checkedAll"> 全选按钮</p><p><input type"checkbox" class"cl"> 选项1</p><p><input type"checkbox&qu…...
直接修改zynq petalinux编译出来的rootfs.cpio.gz文件内容
xilinx zynq petalinux 默认编译打包出的SPI flash烧写启动文件是BOOT.BIN,然而每次需要修改rootfs内的文件时都要重新build rootfs 然后再 package一次才能生成新的BOOT.bin文件,地球人都知道petalinux编译一次是很耗时间的,那么有没有什么简…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...