技术成神之路:设计模式(一)单例模式
在软件设计中,有时我们希望某个类的实例始终是唯一的,即无论在何处访问这个类,都能够得到同一个实例。单例模式(Singleton Pattern)就是为了解决这个问题而产生的。单例模式确保一个类只有一个实例,并提供一个全局访问点。
1.定义
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。其主要思想是将类的构造函数私有化,并通过一个静态方法来控制实例的创建和访问。
2.常见实现方式
单例模式有多种实现方式,下面介绍几种常见的实现方式:
2.1饿汉式(Eager Initialization)
饿汉式是在类加载时就创建实例,这样可以确保线程安全,并且在类首次使用前完成实例化。
示例代码:
public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {// 私有构造函数,防止外部实例化}public static Singleton getInstance() {return INSTANCE;}
}
优点:简单,易于理解,线程安全
缺点:类加载时即创建实例,可能造成资源浪费
如果你一定会使用该类,这种方式无疑是最简单的方法
2.2 懒汉式(Lazy Initialization)
懒汉式是在第一次调用 getInstance() 方法时创建实例。这种方式避免了饿汉式的资源浪费问题。
示例代码:
public class Singleton {private static Singleton instance;private Singleton() {// 私有构造函数,防止外部实例化}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}
优点:实现简单,延迟实例化,避免资源浪费
缺点:使用了 synchronized,在高并发情况下性能可能较差
每次调用getInstance()
都会进行同步检查,这样会消耗不必要的资源,不推荐使用
2.3双重检查锁(Double-Checked Locking)
双重检查锁在懒汉式的基础上,通过减少使用 synchronized 来提高性能。
示例代码:
public class Singleton {// volatile关键字确保多线程下的可见性和有序性(禁止字节码重排)private static volatile Singleton instance;private Singleton() {// 私有构造函数,避免外部直接实例化}public static Singleton getInstance() {if (instance == null) { // 第一次检查synchronized (Singleton.class) {if (instance == null) { // 第二次检查instance = new Singleton(); // 实例化}}}return instance; // 返回实例}
}
优点:延迟实例化,提高了性能
缺点:实现复杂,容易出错
同步代码块含义:因为可能会有多个线程同时通过了第一次检查,在进入同步块之后,再次检查可以确保只有一个线程创建实例,最大限度地在提升性能的条件下保证了线程安全。
emm… 个人不喜欢这种笨重写法
2.4 静态内部类(Static Inner Class)
这种方式使用了类加载机制来确保线程安全,同时实现了延迟加载。
示例代码:
public class Singleton {private Singleton() {// 私有构造函数,防止外部实例化}// 静态内部类,利用类加载机制保证线程安全且延迟加载private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}
优点:延迟实例化,线程安全,实现简单
缺点:无法传递外部参数
这时候就会有同学要问了,何为类加载机制,问的好,所谓类加载机制就算:JVM 在加载类的过程中,静态内部类 SingletonHolder 中的静态变量 INSTANCE 只会被实例化一次,由JVM保证其线程安全性,所以在多线程环境下可以安全地使用。
2.5 枚举(Enum)
这种方法是Effective Java作者Joshua Bloch推荐的单例实现方式之一,它解决了传统单例模式实现中的一些问题,比如序列化、反射攻击等。
示例代码:
public enum Singleton {INSTANCE;public void doSomething() {// 业务方法}
}
优点:简洁,线程安全,防止反序列化破坏单例
缺点:无法灵活控制实例化过程
使用方法:
Singleton.INSTANCE.doSomething();
特点和优势
-
线程安全性:
枚举类型的实例创建是线程安全的,JVM在加载枚举类型时会通过类加载器保证只实例化一次。因此,多线程环境下也能保证单例的唯一性。 -
防止反射攻击:
枚举类型的实例创建是由JVM控制的,因此无法通过反射来创建枚举类的实例。这样可以防止反射攻击,即使是在枚举类中添加了私有构造函数也不例外。 -
防止序列化问题:
Java枚举类型在序列化和反序列化时会自动处理,确保在序列化和反序列化过程中都是单例的。 -
简洁且高效:
枚举实现单例模式非常简洁,只需声明一个枚举类型即可,不需要额外的代码来保证线程安全和单例特性。
3.单例模式的注意事项
- 线程安全:确保在多线程环境下一个类只有一个实例。
- 延迟加载:尽量避免在类加载时就实例化,除非明确知道实例一定会被使用。
- 防止反射攻击:通过在构造函数中添加判断来防止反射创建多个实例。
- 防止反序列化破坏单例:在实现
Serializable
接口时,提供 `readResolve 方法。
4.总结
五种创建单例的方式,大家按需选择,核心思想都是确保一个类只有一个实例,并提供全局访问点,没有最好的,只有最适合的,理解不同实现方式的优缺点,可以帮助我们在实际开发中选择最合适的方案。
相关文章:
技术成神之路:设计模式(一)单例模式
在软件设计中,有时我们希望某个类的实例始终是唯一的,即无论在何处访问这个类,都能够得到同一个实例。单例模式(Singleton Pattern)就是为了解决这个问题而产生的。单例模式确保一个类只有一个实例,并提供一…...

四、(3)补充beautifulsoup、re正则表达式、标签解析
四、(3)补充beautifulsoup、re正则表达式、标签解析 beautifulsoupre正则表达式正则提取标签解析 beautifulsoup 补充关于解析的知识 还需要看爬虫课件 如何定位文本或者标签,是整个爬虫中非常重要的能力 无论find_all(ÿ…...

Vscode快捷键崩溃
Vscode快捷键崩溃 Linux虚拟机下使用vscode写代码【ctrlA,CtrlC,CtrlV】等快捷键都不能使用,还会出现“NO text insert“等抽象的指令,问题就是不知道什么时候装了一个VIM插件,让他滚出电脑》》》...
Spring Boot中的开发工具与插件推荐
Spring Boot中的开发工具与插件推荐 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们来聊聊Spring Boot中的开发工具与插件推荐。Spring Boot作为一种简…...

qt6 获取百度地图(一)
需求分析: 要获取一个地图, 需要ip 需要根据ip查询经纬度 根据经纬度查询地图 另外一条线是根据输入的地址 查询ip 根据查询到的ip查地图‘ 最后,要渲染地图 上面这这些动作,要进行http查询: 为此要有三个QNet…...
overlap的uORF对TE的抑制程度为什么显著高于non-overlap的uORF
在翻译调控中,上游开放阅读框(uORFs)对主开放阅读框(main ORF)的抑制效果有很大差异,尤其是重叠的uORFs(overlap uORFs)通常比非重叠的uORFs(non-overlap uORFsÿ…...

面向高精度导航定位领域的UM980RTK定位模块
UM980 是和芯星通自主研发的新一代 BDS/GPS/GLONASS/Galileo/QZSS 全系统全频高精度 RTK 定位模块,基于和芯星通自主研发的新一代射频基带及高精度算法一体化GNSS SoC 芯片—NebulasIV 设计。可同时跟踪 BDS, GPS, GLONASS, Galileo, QZSS, NavIC, SBAS, L-Band* 等…...

145-四路16位125Msps AD FMC子卡模块
一、概述 该板卡可实现4路16bit 125Msps AD 功能,是xilinx开发板设计的标准板卡。FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设备中,特别是在xilinx公司的所有开发板中都使用。该AD,DA子卡模块就专门针对xilinx开发…...
服务器被劫持
当服务器被劫持时,可以采取一系列措施来修复和加强安全防护,确保服务器的安全性和数据的完整性。以下是一些建议的步骤和策略:12 确认服务器被劫持:首先需要确认服务器是否被劫持。这可以通过检查服务器的日志、网络流量、以及任…...

康姿百德磁性床垫好不好,效果怎么样靠谱吗
康姿百德典雅款床垫,打造舒适睡眠新体验 康姿百德床垫是打造舒适睡眠新体验的首选,其设计能够保护脊椎健康,舒展脊椎,让您享受一夜好眠。康姿百德床垫的面料选择也非常重要,其细腻亲肤的针织面料给您带来柔软舒适的触…...

[吃瓜教程]南瓜书第5章神经网络
1.M-P神经元 M-P神经元,全称为McCulloch-Pitts神经元,是一种数学模型,用于模拟生物神经元的功能。这个模型是由Warren McCulloch和Walter Pitts在1943年提出的。它是人工智能和计算神经科学领域中非常重要的早期模型。 M-P神经元接收n个输入…...

装饰模式解析:基本概念和实例教程
目录 装饰模式装饰模式结构装饰模式应用场景装饰模式优缺点练手题目题目描述输入描述输出描述题解 装饰模式 装饰模式,又称装饰者模式、装饰器模式,是一种结构型设计模式,允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行…...
211.xv6——3(page tables)
在本实验室中,您将探索页表并对其进行修改,以简化将数据从用户空间复制到内核空间的函数。 开始编码之前,请阅读xv6手册的第3章和相关文件: kernel/memlayout.h,它捕获了内存的布局。kernel/vm.c,其中包含…...
yum使用报错:ImportError: /lib64/libxml2.so.2: file too short
系统版本:Rocky 8.10 报错信息: Traceback (most recent call last):File "/usr/lib64/python3.6/site-packages/libdnf/error.py", line 14, in swig_import_helperreturn importlib.import_module(mname)File "/usr/lib64/python3.6/i…...

【Android面试八股文】你是怎么保证Android设备的时间与服务器时间同步的?(使用NTP和TrueTime方案)
文章目录 一、网络时间协议(NTP)二、使用网络时间协议(NTP)2.1 使用系统提供的 NTP 服务器2.2 使用TrueTime2.2.1 引入TrueTime库2.2.2 初始化 TrueTime2.2.3 用法2.2.4 使用 TrueTime 获取时间2.2.4 自动更新时间2.2.5 注意事项二. 使用 HTTP 请求获取服务器时间2.1. 发送…...

解决Python爬虫开发中的数据输出问题:确保正确生成CSV文件
引言 在大数据时代,爬虫技术成为获取和分析网络数据的重要工具。然而,许多开发者在使用Python编写爬虫时,常常遇到数据输出问题,尤其是在生成CSV文件时出错。本文将详细介绍如何解决这些问题,并提供使用代理IP和多线程…...

SCI一区TOP|徒步优化算法(HOA)原理及实现【免费获取Matlab代码】
目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年,SO Oladejo受到徒步旅行启发,提出了徒步优化算法(Hiking Optimization Algorithm, HOA)。 2.算法原理 2.1算法思想 HOA灵感来自于…...
Android的activity广播无法接收,提示process gone or crashing原因有可能是那些?
当Android的Activity无法接收广播,并且收到“process gone or crashing”的提示时,可能的原因有多种。以下是一些常见的原因和排查步骤: Activity生命周期问题: 如果Activity在广播发送之前就已经被销毁(例如…...
如何将等保2.0的要求融入日常安全运维实践中?
等保2.0的基本要求 等保2.0是中国网络安全领域的基本国策和基本制度,它要求网络运营商按照网络安全等级保护制度的要求,履行相关的安全保护义务。等保2.0的实施得到了《中华人民共和国网络安全法》等法律法规的支持,要求相关行业和单位必须按…...

51单片机嵌入式开发:STC89C52环境配置到点亮LED
STC89C52环境配置到点亮LED 1 环境配置1.1 硬件环境1.2 编译环境1.3 烧录环境 2 工程配置2.1 工程框架2.2 工程创建2.3 参数配置 3 点亮一个LED3.1 原理图解读3.2 代码配置3.3 演示 4 总结 1 环境配置 1.1 硬件环境 硬件环境采用“华晴电子”的MINIEL-89C开发板,这…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...