一、单例模式

文章目录

  • 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() 时才创建单例。
  • 线程不安全:如果有多个线程同时通过了 if (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 单例模式的使用场景

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/46453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷粒商城-全文检索-ElasticSearch

1.简介 一个分布式的开源搜索和分析引擎,可以 秒 级的从海量数据中检索 主要功能:做数据的检索和分析(MySQL专攻于数据的持久化存储与管理CRUD达到百万以上的数据MSQL就会很慢,海量数据的检索和分析还是要用ElasticSearch) 用途:我们电商项目里的所有的检索功能都是由Elasti…

基于X86+FPGA+AI数字化医疗设备:全自动尿沉渣检测仪

助力数字医疗发展,信迈可提供全自动尿沉渣检测仪专用计算机 随着信息技术的不断进步,医疗也进入了一个全新的数字化时代。首先是医疗设备的数字化,大大丰富了医疗信息的内涵和容量,具有广阔的市场发展前景。 数字化医疗设备&…

使用Redis的SETNX命令实现分布式锁

什么是分布式锁 分布式锁是一种用于在分布式系统中控制多个节点对共享资源进行访问的机制。在分布式系统中,由于多个节点可能同时访问和修改同一个资源,因此需要一种方法来确保在任意时刻只有一个节点能够对资源进行操作,以避免数据不一致或…

嵌入式香橙派人工智能AI开发板详细操作与远程聊天实现

大家好,今天给大分享一个OrangePi AIpro(20T)采用昇腾作为主控芯片的开发板,开箱以及对应功能的详细实现。 第一:板子基本介绍 接通电源给对应的开发板上电,观察其中的现象,如下: 注…

基于HAL库的stm32的OLED显示屏显示(IIC)

OLED OLED,即有机发光二极管( Organic Light Emitting Diode )。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器…

龙国专利局瑞数6

声明(lianxi a15018601872) 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 前言(lianxi a…

配置和保护SSH

使用SSH访问远程命令行 描述Secure Shell SSH(Secure Shell) 是一种网络协议,用于在不安全的网络上安全地进行系统管理和数据传输。它最初由 Tatu Ylnen 于1995年设计,并成为保护网络服务免受攻击的标准。SSH提供了多种功能&…

基于SpringBoot+Vue的广场舞团系统(带1w+文档)

基于SpringBootVue的广场舞团系统(带1w文档) 基于SpringBootVue的广场舞团系统(带1w文档) 广场舞团,为用户随时随地查看广场舞团信息提供了便捷的方法,更重要的是大大的简化了管理员管理广场舞团信息的方式方法,更提供了其他想要了解广场舞团…

基于Trace的类型特化动态语言JIT编译

文章目录 Explain一、简介二、一个跟踪运行的示例三、跟踪树3.1 Traces类型特化(Type specialization) 3.2 Trace Trees3.3 黑名单(Blacklisting) 四、嵌套跟踪树4.1 Nesting Algorithm4.2 Blacklisting with Nesting 五、跟踪树优…

【Pytorch】一文向您详细介绍 torch.randn_like()

🎉🔥【Pytorch】一文向您详细介绍 torch.randn_like() 🔥🎉 下滑即可查看博客内容 🌈 欢迎莅临我的个人主页 👈这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地!🎇 …

滑动窗口题目

题目描述&#xff1a; 计算两个字符串str1和str2在给定的含有n个元素的字符串数组strs中出现的最短距离。 详细解释&#xff1a; 定义整数变量n&#xff0c;用于存储字符串数组strs的长度。定义一个vector<string>类型的变量strs&#xff0c;用于存储输入的字符串。定义…

破解反爬虫策略 /_guard/auto.js(一) 原理

背景 当用代码或者postman访问一个网站的时候&#xff0c;访问他的任何地址都会返回<script src"/_guard/auto.js"></script>&#xff0c;但是从浏览器中访问显示的页面是正常的&#xff0c;这种就是网站做了反爬虫策略。本文就是带大家来破解这种策略&…

4.3 最小二乘近似

一、最小二乘解 A x b A\boldsymbol x\boldsymbol b Axb 经常无解&#xff0c;一般是因为方程太多了。矩阵 A A A 的行比列要多&#xff0c;即方程要多余未知数&#xff08; m > n m>n m>n&#xff09;。 n n n 个列只能张成 m m m 空间的一小部分&#xff0c;除非…

面向铁路、地铁旅客信息系统(PIS)的上架型整机,铁路专用M12网络接口,满足欧洲铁路应用标准

上架型整机 2U 19寸上架型整机&#xff0c;采用高性能低功耗处理器&#xff0c;能应用在宽温环境下&#xff0c;并满足欧洲铁路应用标准EN50155关于电磁兼容性&#xff0c;冲击和振动测试试验的要求&#xff0c;是一款面向铁路、地铁旅客信息系统&#xff08;PIS&#xff09;的…

C# 关于 PaddleOCRSharp OCR识别的疲劳测试

目录 关于 PaddleOCRSharp 应用范例演示 ​范例运行环境 疲劳测试 添加组件库 方法设计 调用示例 小结 关于 PaddleOCRSharp PaddleOCRSharp 是百度飞桨封装的.NET版本 OCR dll 类库&#xff0c;OCR&#xff08;Optical Character Recognition&#xff09;工具可以将…

【Java面向对象】抽象类和接口

文章目录 1.抽象类2.常见的抽象类2.1 Number类2.2 Calendar 和GregorianCalendar 3.接口4.常见接口4.1 Comparable 接口4.2 Cloneable 接口4.3 深浅拷贝 5.类的设计原则 1.抽象类 在继承的层次结构中&#xff0c;每个新的子类都使类变得更加明确和具体。如果从一个子类向父类追…

Unty 崩溃问题(Burst 1.8.2)

错误代码&#xff1a; Assertion failed on expression: exception SCRIPTING_NULL UnityEngine.StackTraceUtility:ExtractStackTrace () Unity.Burst.BurstCompiler:SendRawCommandToCompiler (string Unity版本&#xff1a;2021.3.17F1&#xff0c;Burst 1.8.2 表现&…

python安装talib库教程

【talib介绍】 Talib介绍 Talib&#xff0c;全称“Technical Analysis Library”&#xff0c;即技术分析库&#xff0c;是一个广泛应用于金融量化领域的Python库。该库由C语言编写&#xff0c;支持Python调用&#xff0c;为投资者、交易员和数据分析师提供了强大的技术分析工…

酷炫末世意境背景404单页HTML源码

源码介绍 酷炫末世意境背景404单页HTML源码&#xff0c;背景充满着破坏一切的意境&#xff0c;彷佛末世的到来&#xff0c;可以做网站错误页或者丢失页面&#xff0c;将下面的代码放到空白的HTML里面&#xff0c;然后上传到服务器里面&#xff0c;设置好重定向即可 效果预览 …

论文学习——基于自适应选择的动态多目标进化优化有效响应策略

论文题目&#xff1a;Effective response strategies based on adaptive selection for dynamic multi-objective evolutionary optimization 基于自适应选择的动态多目标进化优化有效响应策略&#xff08;Xiaoli Li a,b,c, Anran Cao a,∗, Kang Wang a&#xff09;Applied S…