单例模式的八种写法、单例和并发的关系
文章目录
- 1.单例模式的作用
- 2.单例模式的适用场景
- 3.饿汉式
- 静态常量(可用)
- 静态代码块(可用)
- 4.懒汉式
- 线程不安全(不可用)
- 同步方法(线程安全,但不推荐用)
- 同步代码块(线程不安全,不可用)
- 双重检查 + volatile(推荐用)
- 静态内部类(推荐用)
- 枚举(推荐用)
1.单例模式的作用
为什么需要单例?
- 节省内存和计算
- 保证结果正确
- 方便管理
2.单例模式的适用场景
- 无状态的工具类:比如日志工具类,不管是在哪里使用,我们需要的只是它帮我们记录日志信息,除此之外,并不需要在它的实例对象上存储任何状态,这时候我们就只需要一个实例对象即可。
- 全局信息类:比如我们在一个类上记录网站的访问次数,我们不希望有的访问被记录在对象 A 上,有的却记录在对象 B 上,这时候我们就让这个类成为单例。
3.饿汉式
静态常量(可用)
/*** 饿汉式(静态常量)(可用)*/
public class Singleton1 {// 由于加了static关键字,根据JVM的规定,在类加载的时候就会完成INSTANCE的实例化,这样就避免了线程同步问题private final static Singleton1 INSTANCE = new Singleton1();// 构造函数是私有的private Singleton1() {}public static Singleton1 getInstance() {return INSTANCE;}
}
静态代码块(可用)
/*** 饿汉式(静态代码块)(可用)*/
public class Singleton2 {private final static Singleton2 INSTANCE;// 与上一种写法类似,由JVM保证了线程安全static {INSTANCE = new Singleton2();}// 构造函数是私有的private Singleton2() {}public static Singleton2 getInstance() {return INSTANCE;}
}
4.懒汉式
线程不安全(不可用)
/*** 懒汉式(线程不安全)(不可用)*/
public class Singleton3 {private static Singleton3 instance;// 构造函数是私有的private Singleton3() {}public static Singleton3 getInstance() {// 这种写法是线程不安全的,不可用if (instance == null) {instance = new Singleton3();}return instance;}
}
同步方法(线程安全,但不推荐用)
/*** 懒汉式(线程安全)(不推荐用)*/
public class Singleton4 {private static Singleton4 instance;// 构造函数是私有的private Singleton4() {}// 这种写法虽然是线程安全的,但是效率太低,不推荐用public synchronized static Singleton4 getInstance() {if (instance == null) {instance = new Singleton4();}return instance;}
}
同步代码块(线程不安全,不可用)
/*** 懒汉式(线程不安全)(不可用)*/
public class Singleton5 {private static Singleton5 instance;// 构造函数是私有的private Singleton5() {}public static Singleton5 getInstance() {// 这种写法并不是线程安全的,不可用if (instance == null) {synchronized (Singleton5.class) {instance = new Singleton5();}}return instance;}
}
双重检查 + volatile(推荐用)
优点:线程安全,延迟加载,效率较高。
/*** 双重检查 + volatile(推荐用)*/
public class Singleton6 {// volatile防止重排序private volatile static Singleton6 instance;// 构造函数是私有的private Singleton6() {}public static Singleton6 getInstance() {// 双重检查保证线程安全if (instance == null) {synchronized (Singleton6.class) {if (instance == null) {instance = new Singleton6();}}}return instance;}
}
为什么要用 volatile?
新建对象 rs = new Resource()
实际上有 3 个步骤:
- construct empty resource()
- call constructor
- assign to rs
如下图所示,重排序会带来NPE问题(NullPointerException, 空指针异常),而使用 volatile 可以防止重排序。
静态内部类(推荐用)
/*** 静态内部类(线程安全,懒加载)(推荐用)*/
public class Singleton7 {// 构造函数是私有的private Singleton7() {}// 由JVM的规定可知,这种写法同时满足了线程安全和懒加载两个优点private static class SingletonInstance {private static final Singleton7 INSTANCE = new Singleton7();}public static Singleton7 getInstance() {return SingletonInstance.INSTANCE;}
}
枚举(推荐用)
单例模式的书写:
/*** 枚举(线程安全,懒加载)(推荐用)*/
public enum Singleton8 {INSTANCE;public void whatever() {}
}
单例的使用:
Singleton8.INSTANCE.whatever();
哪种单例的实现方案最好?
Joshua Bloch 大神在《Effective Java》中明确表达过的观点:使用枚举实现单例的方法虽然还没有广泛采用,但是单元素的枚举类型已经成为实现 Singleton 的最佳方法。
- 写法简单
- 线程安全有保障
- 懒加载
- 避免反序列化破坏单例
相关文章:

单例模式的八种写法、单例和并发的关系
文章目录 1.单例模式的作用2.单例模式的适用场景3.饿汉式静态常量(可用)静态代码块(可用) 4.懒汉式线程不安全(不可用)同步方法(线程安全,但不推荐用)同步代码块…...

基于实时Linux+FPGA实现NI CompactRIO系统详解
利用集成的软件工具链,结合信号调理I/O模块,轻松构建和部署实时应用程序。 什么是CompactRIO? CompactRIO系统提供了高处理性能、传感器专用I/O和紧密集成的软件工具,使其成为工业物联网、监测和控制应用的理想之选。实时处理器提…...

Webhook端口中的自定义签名身份认证
概述 如果需要通过 Webhook 端口从交易伙伴处接收数据,但该交易伙伴可能对于安全性有着较高的要求,而不仅仅是用于验证入站 Webhook 要求的基本身份验证用户名/密码,或者用户可能只想在入站 Webhook 消息上增加额外的安全层。 使用 Webhook…...

用Linux的视角来理解缓冲区概念
缓冲区的认识 缓冲区(buffer)是存储数据的临时存储区域。当我们用C语言向文件中写入数据时,数据并不会直接的写到文件中,中途还经过了缓冲区,而我们需要对缓冲区的数据进行刷新,那么数据才算写到文件当中。…...
C#中Enumerable.Range(Int32, Int32) 方法用于计算
目录 一、关于Enumerable.Range(Int32, Int32) 方法 1.定义 2.Enumerable.Range()用于数学计算的操作方法 3.实例1:显示整型数1~9的平方 4.实例2:显示整型数0~9 5.实例3:Enumerable.Range()vs for循环 &#x…...
Linux和windows进程同步与线程同步那些事儿(四):windows 下进程同步
Linux和windows进程同步与线程同步那些事儿(一) Linux和windows进程同步与线程同步那些事儿(二): windows线程同步详解示例 Linux和windows进程同步与线程同步那些事儿(三): Linux线…...
1. Logback介绍
Logback介绍 Logback旨在成为流行的log4j项目的继任者。它由Ceki Glc设计,他是log4j的创始人。它基于十年在设计工业级日志系统方 面的经验。结果产品,即logback,比所有现有的日志系统更快,具有更小的占用空间,有时差距…...

SqueezeNet:通过紧凑架构彻底改变深度学习
一、介绍 在深度学习领域,对效率和性能的追求往往会带来创新的架构。SqueezeNet 是神经网络设计的一项突破,体现了这种追求。本文深入研究了 SqueezeNet 的复杂性,探讨其独特的架构、设计背后的基本原理、应用及其对深度学习领域的影响。 在创…...
Python:正则表达式之re.group()用法
Python正则表达式之re.group()用法学习笔记 正则表达式是在处理字符串时非常有用的工具,而re.group()是在匹配到的文本中提取特定分组内容的方法之一。 1. re.group()的基本用法 在正则表达式中,通过圆括号可以创建一个或多个分组。re.group()用于获取…...

Shiro框架:Shiro登录认证流程源码解析
目录 1.用户登录认证流程 1.1 生成认证Token 1.2 用户登录认证 1.2.1 SecurityManager login流程解析 1.2.1.1 authenticate方法进行登录认证 1.2.1.1.1 单Realm认证 1.2.1.2 认证通过后创建登录用户对象 1.2.1.2.1 复制SubjectContext 1.2.1.2.2 对subjectContext设…...

WEB前端人机交互导论实验-实训2格式化文本、段落与列表
1.项目1 文本与段落标记的应用: A.题目要求: B.思路: (1)首先,HTML文档的基本结构是通过<html>...</html>标签包围的,包含了头部信息和页面主体内容。 (2)在头部信息…...
Python:list列表与tuple元组的区别
在Python中,List(列表) 和Tuple(元组) 都是用于存储一组有序元素的数据结构,但它们有一些关键的区别,包括可变性、性能、语法等方面。 1. List(列表) 用法:…...

如何基于 Gin 封装出属于自己 Web 框架?
思路 在基于 Gin 封装出属于自己的 Web 框架前,你需要先了解 Gin 的基本用法和设计理念。 然后,你可以通过以下步骤来封装自己的 Web 框架: 封装路由:Gin 的路由是通过 HTTP 方法和 URL 路径进行匹配的,你可以根据自己…...

VUE element-ui实现表格动态展示、动态删减列、动态排序、动态搜索条件配置、表单组件化。
1、实现效果 1.1、文件目录 1.2、说明 1、本组件支持列表的表头自定义配置,checkbox实现 2、本组件支持列表列排序,vuedraggable是拖拽插件,上图中字段管理里的拖拽效果 ,需要的话请自行npm install 3、本组件支持查询条件动态…...

压测工具ab
Apache Benchmark(简称ab) 是Apache安装包中自带的压力测试工具 ,简单易用, Apache的ab命令模拟多线程并发请求,测试服务器负载压力,也可以适用于其他服务:nginx、lighthttp、tomcat、IIS等其它Web服务器的压力 采用平台…...

P4学习(一) 环境搭建
系列文章目录 第一章 P4学习入门之虚拟机环境搭建 文章目录 系列文章目录前言一、P4是什么?二、搭建步骤1.下载虚拟机镜像2.虚拟机管理软件载入镜像2.1 找到你镜像的所在位置2.2 打开VMware Workstation2.3 载入镜像 3.检验环境是否配置成功 P4 的真机环境搭建 前言…...

openssl3.2 - 官方demo学习 - server-arg.c
文章目录 openssl3.2 - 官方demo学习 - server-arg.c概述笔记备注END openssl3.2 - 官方demo学习 - server-arg.c 概述 TLS服务器, 等客户端来连接; 如果客户端断开了, 通过释放bio来释放客户端socket, 然后继续通过bio读来aceept. 笔记 对于开源工程, 不可能有作者那么熟悉…...

Windows RPC运行时漏洞事后总结
2022年4月前后,Windows RPC运行时被曝出存在远程代码执行漏洞,当时曾引起很多人广泛关注。微软很快做出反应,发布补丁程序进行修补。这次事件中,Windows远程过程调用(RPC)运行时共出现三个关键漏洞…...

运算电路(1)——加法器
一、引言 微处理器是由一片或少数几片大规模集成电路组成的中央处理器。这些电路执行控制部件和算术逻辑部件的功能。微处理器能完成取指令、执行指令,以及与外界存储器和逻辑部件交换信息等操作,是微型计算机的运算控制部分。它可与存储器和外围电路芯片…...
ESP32-WIFI(Arduino)
ESP32-WIFI Wi-Fi是一种基于IEEE 802.11标准的无线局域网技术,是Wi-Fi联盟制造商的商标作为产品的品牌认证。它可以让电脑、手机、平板电脑等设备通过无线信号连接到互联网 。 在无线网络中,AP(Access Point)和 STA(St…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
用鸿蒙HarmonyOS5实现中国象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
FOPLP vs CoWoS
以下是 FOPLP(Fan-out panel-level packaging 扇出型面板级封装)与 CoWoS(Chip on Wafer on Substrate)两种先进封装技术的详细对比分析,涵盖技术原理、性能、成本、应用场景及市场趋势等维度: 一、技术原…...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...