《单例模式的深度解读:实现方式、破坏情况与利弊权衡》
单例模式
一、单例模式的定义
单例模式(Singleton Pattern)是一种常见的软件设计模式,确保一个类只有一个实例存在,并提供一个全局访问点来获取该实例。
二、单例模式的实现方式
1.懒汉式单例
public class LazySingleton {private static LazySingleton instance; // 静态变量存储唯一实例private LazySingleton() { // 私有构造函数,防止外部创建实例System.out.println("懒汉式单例构造函数被调用");}public static LazySingleton getInstance() { // 获取实例的静态方法if (instance == null) { // 如果实例尚未创建instance = new LazySingleton(); // 创建实例System.out.println("懒汉式单例实例首次创建");}return instance; // 返回实例}
}
在懒汉式中,只有在第一次调用 getInstance 方法时才创建实例。
2.饿汉式单例
public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton(); // 直接创建并初始化唯一实例private EagerSingleton() { // 私有构造函数System.out.println("饿汉式单例构造函数被调用");}public static EagerSingleton getInstance() { // 获取实例的静态方法System.out.println("饿汉式单例实例获取");return instance; }
}
饿汉式在类加载时就创建了实例。
3.双重检验锁(Double Check Lock,DCL)
private volatile static Singleton singleton; // 使用volatile修饰,保证线程可见性
private Singleton (){} // 私有构造函数,防止外部直接实例化/*** 获取单例实例的方法* @return 单例对象*/
public static Singleton getInstance() {if (singleton == null) { // 第一次检查,避免不必要的同步synchronized (Singleton.class) { // 同步锁,保证线程安全if (singleton == null) { // 第二次检查,确保在同步块内只创建一次实例singleton = new Singleton(); // 创建单例实例}}}return singleton; // 返回单例实例
}
DCL 模式的突出特点在于,它成功地在确保线程安全的基础上,于多线程环境中依然能够维持出色的性能表现。通过巧妙地进行两次 singleton 是否为 null 的判断,有效地规避了不必要的同步操作所带来的性能损耗。
4.静态内部类
private static class SingletonHolder { // 静态内部类private static final Singleton INSTANCE = new Singleton(); // 在内部类中创建单例实例
}
private Singleton (){} // 私有构造函数,防止外部直接实例化/*** 获取单例实例的方法* @return 单例对象*/
public static final Singleton getInstance() {return SingletonHolder.INSTANCE; // 直接返回静态内部类中的单例实例
}
它专门适用于静态域的场景。巧妙地借助了 Java 的类加载机制,仅在实际需要获取实例时才对静态内部类进行加载,从而顺利实现了延迟初始化的效果,同时也切实保障了线程的安全性。
5.枚举
public enum Singleton { // 定义枚举类型的单例INSTANCE; // 唯一的枚举值即单例实例
}
它能够自动支持序列化机制,并且从根本上杜绝了多次实例化的可能性,是一种简洁、高效且极为可靠的单例实现手段。
三、破坏单例的情况及解决方法
-
反射破坏单例
- 问题:通过反射可以绕过私有构造函数的限制创建新的实例。
- 解决:在构造函数中进行判断,如果已经存在实例,抛出异常。
/*** 四、破坏单例的情况及解决方法*//*** 反射破坏单例的解决示例* 问题:通过反射可以绕过私有构造函数的限制创建新的实例。* 解决:在构造函数中进行判断,如果已经存在实例,抛出异常。*/ public class SafeSingleton {private static SafeSingleton instance; // 静态变量存储唯一实例/*** 私有构造函数* 在构造函数中检查是否已有实例存在,若有则抛出运行时异常*/private SafeSingleton() {if (instance!= null) {throw new RuntimeException("单例模式,禁止通过反射创建多个实例!");}}/*** 获取单例实例的方法* 如果实例不存在则创建,存在则直接返回* @return 单例对象*/public static SafeSingleton getInstance() {if (instance == null) {instance = new SafeSingleton();}return instance;} }/*** 序列化和反序列化破坏单例的解决示例* 问题:序列化后再反序列化可能创建新的实例。* 解决:实现 readResolve 方法返回已有的实例。*/ public class SerializableSingleton implements Serializable {private static final SerializableSingleton instance = new SerializableSingleton(); // 初始化唯一实例/*** 私有构造函数*/private SerializableSingleton() {}/*** 获取单例实例的方法* @return 单例对象*/public static SerializableSingleton getInstance() {return instance;}/*** 在反序列化时调用,返回已有的实例* @return 已有的单例实例*/private Object readResolve() {return instance;} }/*** 克隆破坏单例的解决示例* 问题:若单例类实现了 Cloneable 接口,通过克隆可能创建新实例。* 解决:在 clone 方法中抛出异常或返回已有实例。*/ public class CloneableSingleton implements Cloneable {private static CloneableSingleton instance = new CloneableSingleton(); // 存储唯一实例/*** 私有构造函数*/private CloneableSingleton() {}/*** 获取单例实例的方法* @return 单例对象*/public static CloneableSingleton getInstance() {return instance;}/*** 重写 clone 方法,抛出不支持克隆的异常* @return 抛出异常,禁止克隆* @throws CloneNotSupportedException 不支持克隆异常*/@Overrideprotected Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException("单例模式,禁止克隆!");} }四、总结
适用场景:
单例模式适用于在任何情况下都绝对只需要一个实例的情况,例如ServletContext、ServletConfig、ApplicationContext、DBPool、ThreadPool等。优点:
- 在内存中仅存在一个实例,显著降低了内存开销。
- 能够有效避免对资源的多重占用,保证资源的合理分配和使用。
- 设定了全局访问点,从而实现了对访问的严格管控。
缺点:
- 没有提供接口,导致扩展较为困难。
- 若要对单例对象进行扩展,只能通过修改代码来实现,缺乏其他灵活的途径。
总的来说,单例模式在特定场景下能够发挥其优势,有效地管理资源和控制访问,但在扩展性方面存在一定的局限性。在实际应用中,需要根据具体需求权衡其利弊,选择是否使用单例模式。
相关文章:
《单例模式的深度解读:实现方式、破坏情况与利弊权衡》
单例模式 一、单例模式的定义 单例模式(Singleton Pattern)是一种常见的软件设计模式,确保一个类只有一个实例存在,并提供一个全局访问点来获取该实例。 二、单例模式的实现方式 1.懒汉式单例 public class LazySingle…...
010607电压源和电流源受控源
电源的理论部分 1.6电压源和电流源1.理想电压源: 1.6电压源和电流源 1.理想电压源: 其两端电压总能保持定值或一定的时间函数,其值与流过它的电流i无关的元件叫理想电压源。 电路符号:中间与导线直通的圆圈 电压源:…...
快乐数求解
编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1,…...
运维高级内容--为端口做标记、制定调度规则
rs: yum install mod_ssl -y #安装mod_ssl模块 让rs支持https systemctl restart http lvs: cd /boot/ ls less config-5.14.0-427.13.1.el9_4.x86_64 ipvsadm -A -t 192.168.0.200:80 -s rr ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1 #轮询调度一次…...
后端Web之HTTP协议基础介绍
目录 1.HTTP概念 2.HTTP请求协议 3.HTTP响应协议 4.HTTP协议解析 1.HTTP概念 HTTP(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是万维网数据通信的基础,允许将超…...
深入解析Nginx限流策略:如何高效控制访问频率
摘要:本文将详细介绍Nginx限流模块的使用方法,包括基于IP地址的限流、基于并发连接的限流以及如何应对突发流量。通过实际案例,帮助读者掌握Nginx限流策略,确保服务器在高并发场景下的稳定运行。 一、引言 在高并发场景下&#x…...
锂电池剩余寿命预测 | Matlab基于Transformer-GRU的锂电池剩余寿命预测
目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于Transformer-GRU的锂电池剩余寿命预测,Transformer结合门控循环单元。 Matlab基于Transformer-GRU的锂电池剩余寿命预测(单变量) 运行环境Matlab2023b及以上。 首先从…...
深入理解Spring的IOC容器与依赖注入
深入理解Spring的IOC容器与依赖注入 引言 Spring框架的核心功能之一就是它的IOC容器,它为开发人员提供了强大的依赖管理和控制反转的能力。本文将详细介绍Spring的IOC容器以及依赖注入的基本概念和实现方式,并通过示例展示如何在实际项目中应用这些技术…...
Qt读写sysfs
本文介绍Qt读写sysfs。 在嵌入式Linux系统上开发Qt应用程序,经常会涉及到外设的控制,比如GPIO,PWM的控制,Linux环境下可以像操作文件一样操作它们,这通常会涉及到sysfs的读写。本文以读写GPIO为例,简要介绍…...
实景三维:解锁地理信息新维度,引领未来城市智慧之钥
在这个信息爆炸与科技日新月异的时代,地理信息与遥感技术正以前所未有的速度改变我们认知世界的方式。在推动“实景三维平台”这一前沿科技的构建上,它不仅是地理信息的立体呈现,更是智慧城市的基石,打开了通往未来城市规划、管理…...
汽车免拆诊断案例 | 2010款劳斯莱斯古斯特车中央信息显示屏提示传动系统故障
故障现象 一辆2010款劳斯莱斯古斯特车,搭载N74发动机,累计行驶里程约为11万km。车主反映,起动发动机后组合仪表和中央信息显示屏均提示传动系统故障。用故障检测仪检测,发现发动机控制模块2(DME2)中存储…...
监督学习和无监督学习是什么?
监督学习和无监督学习是机器学习中的两种基本学习方式,它们在处理数据和训练模型时有着显著的区别。 监督学习 定义: 监督学习是指利用一组已知类别的样本(即标记的数据)来调整分类器的参数,使其达到所要求性能的过程…...
YII2的errorHandler.errorAction失效原因
<?phpreturn [components => [errorHandler => [errorAction => site/error,],] ]; 这段配置存在错误,导致错误处理无法生效。为了解决这个问题,我们需要对配置进行优化。 代码查看:yii\web\ErrorHandler::renderException <?phpprotected function ren…...
已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change(p),交换p所指向的结点和它的前缀结点的顺序。
#include<assert.h> typedef struct SLnode {int data;struct SLnode* prior;struct SLnode* next; }SLnode,*SLnodelist; //创建结点 SLnode* createhead(int data) {SLnode* newnode (SLnode*)malloc(sizeof(SLnode));newnode->data data;newnode->next newno…...
什么是Tensor???为什么人工智能领域论文中经常出现这个名词
文章目录 什么是Tensor??数学符号表示 什么是Tensor?? Tensor,中文叫张量。Tensor实际上就是一个多维数组(multidimensional array)。 而Tensor的目的是能够创造更高维度的矩阵、向量。 数学符…...
爬虫练习_01
前言 基础爬虫小练习01 一、requests板块使用 demo_01 import requests from lxml import etreeurl "https://movie.douban.com/top250" headers {"authority": "movie.douban.com","method": "GET","path"…...
Datawhale X 魔搭 AI夏令营第四期 魔搭-AIGC方向 task02笔记
从零入门AI生图原理&实践 是 Datawhale 2024 年 AI 夏令营第四期的学习活动(“AIGC”方向),基于魔搭社区“可图Kolors-LoRA风格故事挑战赛”开展的实践学习。 Datawhale官方的Task2链接:Task02 往期Task1链接:Ta…...
多模态大语言模型的免训练视觉提示学习 ControlMLLM
ControlMLLM: Training-Free Visual Prompt Learning for Multimodal Large Language Models github paper 在本研究中,提出了一种无需进行训练的方法,通过可学习的潜变量优化将视觉提示注入到多模态大型语言模型(MLLMs)中。 在…...
Oracle|DM 常用|不常用 SQL大口袋
目录 一、前言 二、SQL写法 1、sql获取某一条数据中的前一条和后一条 2、实现like多个值的查询(Oracle和dm支持,MySQL未试过) 3、start with connect by prior 使用方法 4、用hextoraw解决select、update、delete语句执行慢 5、ORA-00…...
嵌入式软件--模电基础 DAY 1
C语言的学习告一段落了,要多多注意复习回顾,温故而知新,学习的过程就是与遗忘作斗争。接下来就是嵌入式学习中硬件电路方面的知识了。 一、电学基础 1.电流 电流(Current)是电荷在单位时间内通过导体横截面的流动量…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
