当前位置: 首页 > news >正文

一、单例模式

文章目录

  • 1 基本介绍
  • 2 实现方式
    • 2.1 饿汉式
      • 2.1.1 代码
      • 2.1.2 特性
    • 2.2 懒汉式 ( 线程不安全 )
      • 2.2.1 代码
      • 2.2.2 特性
    • 2.3 懒汉式 ( 线程安全 )
      • 2.3.1 代码
      • 2.3.2 特性
    • 2.4 双重检查
      • 2.4.1 代码
      • 2.4.2 特性
    • 2.5 静态内部类
      • 2.5.1 代码
      • 2.5.2 特性
    • 2.6 枚举
      • 2.6.1 代码
      • 2.6.2 特性
  • 3 实现的要点
  • 4 线程不安全的单例模式
    • 4.1 代码
    • 4.2 评价
  • 5 JDK中的单例模式
  • 6 单例模式的类图及角色
    • 6.1 类图
    • 6.2 角色
  • 7 推荐的单例模式的实现
  • 8 单例模式的使用场景

1 基本介绍

单例模式(Singleton Pattern)是一种 创建型 设计模式,其目的是 确保一个类仅有一个实例,并提供一个 静态方法 来获取该实例。

2 实现方式

单例模式围绕着两个特性展开:

  • 延迟加载:在需要这个单例时才创建单例,避免浪费内存。
  • 线程安全:在多线程环境下,保证多线程使用的单例是同一个单例。

共有以下六种实现方式:

2.1 饿汉式

2.1.1 代码

饿汉式的实现在 Java 中有两种实现,常用的是第一种。

方式一:显式初始化

public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {}public static synchronized Singleton getInstance() {return INSTANCE;}
}

方式二:静态代码块初始化

public class Singleton {private static final Singleton INSTANCE;static {INSTANCE = new Singleton();}private Singleton() {}public static synchronized Singleton getInstance() {return INSTANCE;}
}

2.1.2 特性

  • 不延迟加载:在 类加载 时就创建单例。
  • 线程安全类加载由 JVM 保证线程安全,所以此时创建的单例也是线程安全的。

2.2 懒汉式 ( 线程不安全 )

2.2.1 代码

public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

2.2.2 特性

  • 延迟加载:只有在 调用获取单例的方法 getInstance() 时才创建单例。
  • 线程不安全:如果有多个线程同时通过了 singleton == null 这个条件,则它们会创建多个单例。

2.3 懒汉式 ( 线程安全 )

2.3.1 代码

注意 getInstance() 方法前的 synchronized 修饰符。

public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

2.3.2 特性

  • 延迟加载:只有在 调用获取单例的方法 getInstance() 时才创建单例。
  • 线程安全:在多个线程同时获取单例时,使用 synchronized 互斥锁,来保证只有一个线程能够生成单例,而其他线程等待这个线程创建的单例,保证了单例的线程安全。
  • 成本太大:即使已经有单例了,每次调用 getInstance() 方法还得经过 加锁释放锁 的流程(因为使用了 synchronized 互斥锁),降低了并发性能

2.4 双重检查

2.4.1 代码

注意单例前的 volatile 修饰符,它有两个作用:保证变量对所有线程可见防止指令重排。在此处起 防止指令重排 的作用:防止 JIT 即时编译器对 instance = new Singleton(); 这行代码进行重排序

如果进行重排序,则可能先给 instance 分配内存(此时 instance != null),然后才调用构造器为 instance 的属性赋值。在这两步操作之间,要是有线程调用 getInstance() 方法,它将无法通过外层的 instance == null 条件,会返回一个不完整(赋值不完全)的对象。

public class Singleton {private static volatile Singleton instance; // 注意 volatile 在这里起 防止指令重排 的作用private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}}

2.4.2 特性

  • 延迟加载:只有在 调用获取单例的方法 getInstance() 时才创建单例。
  • 线程安全:在多个线程同时获取单例 且 单例未创建时,如果都通过了外层的 instance == null 条件,则在内层使用 synchronized 互斥锁,来保证只有一个线程创建单例,而其他线程等待这个线程创建的单例,保证了单例的线程安全。
  • 成本小:这种实现方式只有最初创建单例时会加互斥锁,之后就不需要创建单例了,直接返回即可,无需加锁和释放锁,提高了并发性能

2.5 静态内部类

2.5.1 代码

public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

2.5.2 特性

  • 延迟加载:只有在 调用获取单例的方法 getInstance() 时,才会 触发静态内部类的加载,从而创建单例。
  • 线程安全:静态内部类也是类,类加载由 JVM 保证其线程安全,所以本单例是线程安全的。

2.6 枚举

2.6.1 代码

public enum Singleton {INSTANCE; // 直接使用 Singleton.INSTANCE 就可以获取到单例// 可以随意写方法和属性,就像在类中一样
}

2.6.2 特性

  • 不延迟加载:在 类加载 时就创建单例。
  • 线程安全类加载由 JVM 保证线程安全,所以此时创建的单例也是线程安全的。
  • 防止 反射 或 反序列化 破坏单例:其他单例的实现都可以通过 反射 或 反序列化 的方式重新创建新的单例,唯独本实现无法使用这两种方式重新创建新的单例,这是因为 枚举无法通过反射获取对象,并且 枚举在序列化和反序列化时不会调用构造器。所以这种实现是 最推荐的

3 实现的要点

  1. 构造器私有化。例如 private Singleton() {}
  2. 类中有一个 静态 的单例属性。
  3. 提供一个 静态 方法来获取上述单例。

4 线程不安全的单例模式

4.1 代码

public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {instance = new Singleton();}}return instance;}
}

4.2 评价

这样的单例模式是 线程不安全 的,synchronized 互斥锁没有起到应有的作用。只要多个线程都能通过 instance == null 条件,则它们每个线程都会创建一次单例,synchronized 仅仅能保证同一时刻只有一个线程在创建单例罢了。

应该将 判断赋值 都放到 synchronized 互斥锁里,就像单例的 第三种实现——懒汉式 ( 线程安全 ) 一样。

5 JDK中的单例模式

在JDK中,Runtime 类使用了 饿汉式单例,代码如下:

public class Runtime {private static final Runtime currentRuntime = new Runtime();public static Runtime getRuntime() {return currentRuntime;}private Runtime() {}// ...
}

6 单例模式的类图及角色

6.1 类图

alt text
其中,singleton 属性和 Singleton() 构造器都是 私有的,而 getInstance() 方法是 公开的。此外,singleton 属性和 getInstance() 方法都是 静态的

6.2 角色

在单例模式中,只有一个角色 Singleton,它负责 实现返回单例的 静态 方法

7 推荐的单例模式的实现

  1. 饿汉式
  2. 双重检查
  3. 静态内部类
  4. 枚举

8 单例模式的使用场景

  • 创建对象耗时过多或耗费资源过多(重量级),但经常用到。
  • 频繁访问 数据库文件 的对象。
  • 工具类对象。

相关文章:

一、单例模式

文章目录 1 基本介绍2 实现方式2.1 饿汉式2.1.1 代码2.1.2 特性 2.2 懒汉式 ( 线程不安全 )2.2.1 代码2.2.2 特性 2.3 懒汉式 ( 线程安全 )2.3.1 代码2.3.2 特性 2.4 双重检查2.4.1 代码2.4.2 特性 2.5 静态内部类2.5.1 代码2.5.2 特性 2.6 枚举2.6.1 代码2.6.2 特性 3 实现的要…...

B树:高效的数据存储结构

在计算机科学中,B树(B-Tree)是一种平衡多路查找树,它广泛应用于数据库和文件系统等需要高效数据存储和检索的场景。B树的设计旨在优化磁盘I/O操作,通过减少磁盘访问次数来提高数据检索的效率。本文将介绍B树的基本概念…...

[Vulnhub] TORMENT IRC+FTP+CUPS+SMTP+apache配置文件权限提升+pkexec权限提升

信息收集 IP AddressOpening Ports192.168.101.152TCP:21,22,25,80,111,139,143,445,631 $ nmap -p- 192.168.101.152 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 2.0.8 or later | ftp-anon: Anonymous FTP login a…...

<数据集>安全帽佩戴识别数据集<目标检测>

数据集格式:VOCYOLO格式 图片数量:3912张 图片分辨率:640640 标注数量(xml文件个数):3912 标注数量(txt文件个数):3912 标注类别数:2 标注类别名称:[no-helmet, helmet] 序号类别名称图片…...

[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-21 VTC视频时序控制器设计

软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台:https://milianke.tmall.com/ 登录“米联客”FPGA社区 ht…...

记录uni-app横屏项目:自定义弹出框

目录 前言: 正文: 前言:横屏的尺寸问题 最近使用了uniapp写了一个横屏的微信小程序和H5的项目,也是本人首次写的横屏项目,多少是有点踩坑不太适应。。。 先说最让我一脸懵的点,尺寸大小,下面一…...

Linux Vim教程(二):基本命令和操作

目录 1. 进入和退出Vim 1.1 启动Vim 1.2 退出Vim 2. 模式切换 2.1 切换到插入模式 2.2 切换到普通模式 2.3 切换到命令模式 2.4 切换到可视模式 3. 移动光标 4. 编辑文本 4.1 插入和追加文本 4.2 删除文本 4.3 复制和粘贴文本 4.4 撤销和重做 5. 搜索和替换 5.…...

【大模型基础】4.1 数据挖掘(待)

一、什么是文本挖掘? 文本挖掘指的是从文本数据中获取有价值的信息和知识,它是数据挖掘中的一种方法。文本挖掘中最重要最基本的应用是实现文本的分类和聚类,前者是有监督的挖掘算法,后者是无监督的挖掘算法。 二、文本挖掘的作用是什么? 能够从文本数据中获取有价值的…...

Jupyter Notebook与机器学习:使用Scikit-Learn构建模型

Jupyter Notebook与机器学习:使用Scikit-Learn构建模型 介绍 Jupyter Notebook是一款强大的交互式开发环境,广泛应用于数据科学和机器学习领域。Scikit-Learn是一个流行的Python机器学习库,提供了简单高效的工具用于数据挖掘和数据分析。本…...

IMU提升相机清晰度

近期,一项来自北京理工大学和北京师范大学的团队公布了一项创新性的研究成果,他们将惯性测量单元(IMU)和图像处理算法相结合,显著提升了非均匀相机抖动下图像去模糊的准确性。 研究团队利用IMU捕捉相机的运动数据&…...

掌握SQL Server性能监控:自定义性能计数器的实现

掌握SQL Server性能监控:自定义性能计数器的实现 在数据库管理中,监控数据库性能是确保系统稳定运行的关键。SQL Server提供了丰富的性能监控工具,但有时这些工具可能无法满足特定的监控需求。这时,自定义性能计数器就显得尤为重…...

jdk1.8 List集合Stream流式处理

jdk1.8 List集合Stream流式处理 一、介绍(为什么需要流Stream,能解决什么问题?)1.1 什么是 Stream?1.2 常见的创建Stream方法1.3 常见的中间操作1.4 常见的终端操作 二、创建流Stream2.1 Collection的.stream()方法2.2 数组创建流2.3 静态工厂…...

leetcode位运算(1720. 解码异或后的数组)

前言 经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。后续开始专项练习。 描述 未知 整数数组 arr 由 n 个非负整数组成。 经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] arr[i] XOR arr[i 1] 。例如&am…...

Android 性能优化之卡顿优化

文章目录 Android 性能优化之卡顿优化卡顿检测TraceView配置缺点 StricktMode配置违规代码 BlockCanary配置问题代码缺点 ANRANR原因ANRWatchDog监测解决方案 Android 性能优化之卡顿优化 卡顿检测 TraceViewStricktModelBlockCanary TraceView 配置 Debug.startMethodTra…...

mac电脑显示隐藏文件

方法一: 第一步:打开「终端」应用程序。 第二步:输入如下命令: defaults write com.apple.finder AppleShowAllFiles -boolean true ; killall Finder 第三步:按下「Return」键确认。 现在你将会在 Finder 窗口中…...

深度学习之基础知识整理

现在大语言模型很火,但它的基础仍然是以神经网络为基础的深度学习,不懂神经网络,不了解深度学习,对于大语言模型的二次开发也是整不明白。 那到底需要了解哪些知识?才能看懂深度学习/神经网络的基础模型,想…...

R语言学习笔记9-数据过滤-分组-融合

R语言学习笔记9-数据过滤-分组-融合 数据过滤基础数据过滤条件筛选数据使用dplyr包进行数据操作select 函数filter 函数subset函数 数据分组使用split()进行数据分组使用dplyr包进行数据分组使用data.table包进行数据分组 数据融合使用merge()进行数据融合使用dplyr包进行数据融…...

GESP CCF C++ 八级认证真题 2024年6月

第 1 题 GESP活动期间,举办方从获胜者ABCDE五个人中选出三个人排成一队升国旗,其中A不能排在队首,请问 有多少种排法? A.24 B.48 C.32 D.12 第 2 题 7进制数235转换成3进制数是( )。 A. 11121 B. 11…...

Spring Boot 单元测试什么时候需要添加 @RunWith

建立 Spring Boot 单元测试方法一般依赖于 JUnit4 或 JUnit5 框架。 在高版本的 Spring Boot 中,一般默认用的是 JUnit5。此时通过添加 SpringBootTest 注解,即可成功注入相关的 bean 对象,并进行测试。 import org.junit.jupiter.api.Test…...

鸿蒙OpenHarmony Native API【HiLog】

HiLog Overview Description: HiLog模块实现日志打印功能。 开发者可以通过使用这些接口实现日志相关功能,输出日志时可以指定日志类型、所属业务领域、日志TAG标识、日志级别等。 syscap SystemCapability.HiviewDFX.HiLog Since: 8 Summary Files File …...

Pycharm 和虚拟环境的那些事?

背景: 我既有 python 又有Anaconda Pycharm新建虚拟环境: 只说两种方式 通过Virualenv Environment新建: 这里我们勾选上 Make available to all projects ,之后点击🆗 然后可以发现只有非常少的包,因为没有勾选继承 编译器的包 创建的虚拟环境一般目录如下&…...

rancher2里面的containerd的使用

rancher2使用containerd了,在node上去跑docker命令找不到以前的那些pod了,查了很久才设置好crictl的配置 kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP O…...

Python数据风险案例54——人工智能热门概念股爬虫分析其价值(三因子模型)

案例背景 人工智能概念如火如荼的夏天,在这个2024年,我觉得需要提早布局一下这个概念。所以我们找一下A股里面人们的人工智能概念股,然后分析他们的数据应用三因子模型,也就是最经典的资本资产定价模型的衍生版去研究他们各自的投…...

【HarmonyOS开发】Navigation使用

简介 Navigation是路由容器组件,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。适用于模块内和跨模块的路由切换。 在页面跳转时,应该使用页面路由router,在页面内的页面跳转时,建议使用Navigation达到更好的转场动效…...

计算机网络参考模型与5G协议

目录 OSI七层参考模型OSI模型vsTCP/IP模型TCP/IP协议族的组成 OSI七层参考模型 分层功能应用层网络服务与最终用户的一个接口表示层数据的表示,安全,压缩会话层建立,管理,终止会话传输层定义传输数据的协议端口号,以及流控和差错校验网络层进行逻辑地址寻址,实现不同网路之间的…...

docker自建rustdesk-server远程桌面

rustdesk简介 RustDesk 是一款可以平替 TeamViewer 的开源软件,旨在提供安全便捷的自建方案。 RustDesk 是一款功能齐全的远程桌面应用,具有以下特性: 支持 Windows、macOS、Linux、iOS、Android、Web 等多个平台。支持 VP8 / VP9 / AV1 …...

海外抖音黑屏是网络问题还是硬件问题?

随着海外抖音(TikTok)在全球范围内的普及,越来越多的用户开始体验这一短视频社交平台。然而,不少用户在使用过程中遇到了黑屏问题,这让人不禁疑惑:这究竟是网络问题还是硬件问题? 首先&#xf…...

为了实现接口缓存,专门写了个缓存库 f-cache-memory

问题起因 起因是某次发版之后,服务器接口压力过大,当场宕机,排查之后发现有个接口在首页被调十来次(六七年的老项目了,都是泪呀),后端反馈这个接口的sql很复杂,很耗性能&#xff0c…...

actual combat 35 —— es

一、windows中es执行步骤 参考:https://blog.csdn.net/qq_21197507/article/details/115076913 下es安装包下es前端gitHub代码,然后npm -i安装,npm run start 启动安装kibana 二、遇到的问题 1. 第二步安装前端代码依赖报错 npm ERR! co…...

android R ext4 image打包脚本介绍

一、Android R打包指令使用介绍 (1)mkuserimg_mke2fs #./mkuserimg_mke2fs --help usage: mkuserimg_mke2fs [-h] [--android_sparse] [--journal_size JOURNAL_SIZE][--timestamp TIMESTAMP] [--fs_config FS_CONFIG][--product_out PRODUCT_OUT][--b…...

网站建设 财务归类/怎么注册电商平台

随着支付宝小程序的普及和市场占有率的持续提升,越来越多的商家企业都想做支付宝小程序,下面就和大家分享一下支付宝小程序怎么做?什么是支付宝小程序?支付宝小程序是一种全新的开放模式,它运行在支付宝客户端&#xf…...

山东省建设部官方网站/如何网上销售自己的产品

问题总结一、什么是Nginx 是一个轻量级的高性能的反向代理,web服务器,实现非常高效的反向代理,负载均衡,可以处理高并发的连接数,支持5万并发 二、为什么要使用 跨平台性,配置简单, 反向代理&a…...

网站算阵地建设/百度关键词屏蔽

主要分以下步骤: 1)关闭sendmail 2)用yum安装bind-*即DNS的配置 3)yum安装postfix,配置其主配置文件/etc/postfix/main.cf 4)安装cyrus-sasl,配置/etc/sysconfig/saslauthd 5)安装dovecot并进行配置 6)安装cyrus-imapd…...

苏州建设工程招标在哪个网站/网站模板商城

最近两天都在处理这个问题 使用mysql 的时候用到了load data infile 的命令,为什么用这个命令和命令怎么用不解释,参考手册已经很详细了,之说出现的问题。 1.被处理的文件需要严谨的文件格式。 2.路径问题,注意windows 下\\和lin…...

做网站引流做什么类型的网站最好/百度搜索量怎么查

1、明确需求 实战工作中经常会请求各种各样的接口,例如 •微信网页授权接口 • 高德周边检索接口 •发现:下图是根据接口文档开发后的代码,发现代码可读性差(ps. 参数的作用不详) • 解决:通过http_buil…...

有做网站动态效果软件/长沙搜索排名优化公司

编译链接原理 指令:局部函数内部数据:持续整个程序结束----------------------------------------------------------------------------------------------------------------------- (gcc -E .i)预编译(.c): 宏替换、…...