单例模式(饿汉+懒汉)

单例模式

文章目录

  • 单例模式
    • 定义
    • 饿汉式单例
      • **饿汉式单例需要加volatile关键字吗**
      • 类加载过程
    • 懒汉式单列

定义

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点

饿汉式单例

饿汉式单例是Java中实现单例模式的一种方式,它在类加载时就完成了实例化,因此是线程安全的。以下是饿汉式单例的Java实现:

public class Singleton {// 创建Singleton类的一个对象private static Singleton instance = new Singleton();/* 让构造函数为private,这样该类就不会被实例化 */private Singleton() {}/* 获取唯一可用的对象 */public static Singleton getInstance() {return instance;}public static void main(String[] args) {Singleton singleton1 = Singleton.getInstance();Singleton singleton2 = Singleton.getInstance();System.out.println(singleton1 == singleton2); // 输出:true}
}
  1. 将构造函数设为private,防止外部直接通过new Singleton()创建实例。
  2. 在类加载时,静态变量instance就已经初始化,所以它是线程安全的。
  3. 提供一个公共的静态方法getInstance(),用于获取唯一的实例。
  4. 在main方法中,我们创建了两个Singleton实例,由于是同一个实例,所以singleton1和singleton2是相等的

饿汉式单例需要加volatile关键字吗

在饿汉式单例中,通常不需要使用volatile关键字。原因如下:

  • 线程安全性:饿汉式单例在类加载时就完成了实例化,此时类加载是线程安全的。因此,当多个线程同时访问getInstance()方法时,它们看到的instance引用始终指向同一个实例,不需要额外的同步措施。
  • 初始化时机:由于instance在类加载时就已创建,不存在多个线程同时初始化单例的问题,因此不需要volatile来确保内存可见性。
  • 不可变性:instance一旦被初始化,就不会再改变,这满足了不可变对象的特性。对于不可变对象,volatile通常是不必要的。

然而,有一种情况可能需要volatile,那就是如果Singleton类中包含一些动态初始化的属性,这些属性在类加载时可能还没有初始化,那么volatile可以确保所有线程都能看到最新初始化的状态。但这种情况并不常见,因为在饿汉式单例中,通常不推荐有动态初始化的属性。
总结来说,标准的饿汉式单例模式在大多数情况下不需要volatile,因为它已经具备了线程安全性和初始化的原子性。

类加载过程

在Java中,类的加载过程是由类加载器(Class Loader)完成的,包括加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)和初始化(Initialization)。在饿汉式单例模式中,instance的创建发生在初始化阶段,具体步骤如下:

1.加载

  • 类加载器读取字节码文件(.class文件)并将其加载到JVM中。在这个阶段,JVM并不创建类的实例,只是确保类的信息可以被访问。

2.验证

  • 对字节码进行校验,确保它符合Java虚拟机规范,不会对系统造成危害

3.准备

  • 这个阶段,JVM为类的静态字段分配内存,并将其初始化为默认值。对于int类型,如instance,默认值是0。但是,instance在这里并不会被实例化,因为它的类型是引用,所以默认值是null。

4.解析

  • 类的符号引用(如方法名、字段名)被转换为直接引用,这使得JVM可以直接访问这些实体。

5.初始化

  • 这是关键步骤,对于饿汉式单例,初始化时会执行类的静态初始化块(如果有的话)。在饿汉式单例中,instance的初始化就发生在这一阶段。由于instance的初始化表达式new Singleton()是一个静态初始化动作,它会在类初始化时执行,确保instance被创建并赋值为Singleton类的新实例。由于类加载是线程安全的,所以这个过程也是线程安全的。

6.后续使用

  • 当其他代码通过Singleton.getInstance()方法请求单例时,由于instance已经在初始化阶段创建,所以直接返回这个已经存在的实例,无需再次创建。

由于类的初始化(包括静态字段的初始化)是线程安全的,饿汉式单例在类加载时创建的实例对所有线程都是可见的,因此它是线程安全的单例实现。

懒汉式单列

懒汉式单例是指在第一次调用获取实例的方法时才创建单例对象,这是一种延迟加载的方式。为了保证线程安全,可以采用同步锁或双重检查锁定(Double-Checked Locking)的方式来实现。下面是使用双重检查锁定的懒汉式单例的Java实现示例:

public class Singleton {// 使用volatile关键字确保多线程环境下的可见性和禁止指令重排序private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {// 第一次检查:如果instance不为null,直接返回实例,避免同步if (instance == null) {synchronized (Singleton.class) {// 第二次检查:进入同步块后再次检查,以防多线程下重复创建if (instance == null) {instance = new Singleton();}}}return instance;}public static void main(String[] args) {Singleton singleton1 = Singleton.getInstance();Singleton singleton2 = Singleton.getInstance();System.out.println(singleton1 == singleton2); // 输出:true}
}
  1. instance声明为volatile,这是为了确保当instance被初始化成Singleton实例之后,其他线程能够立即看到这个变化,同时也能防止指令重排序带来的问题。
  2. getInstance()方法中首先进行非空检查,如果instance不为null,则直接返回,避免了每次调用都进行同步操作的开销
  3. 只有当instance为null时,才会进入同步块,这是第二次检查,确保在只有一个线程能够执行到创建实例的代码,从而保证了线程安全。
  4. 使用Singleton.class作为同步锁,这是因为类加载器保证了每个类只加载一次,因此对应的.class对象在JVM中也是唯一的,可以安全地作为锁对象。

这种实现方式结合了懒加载和线程安全的优点,同时尽量减少了同步操作带来的性能损耗。

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

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

相关文章

HTML常见标签-标题标签

标题标签 标题标签一般用于在页面上定义一些标题性的内容,如新闻标题,文章标题等,有h1到h6六级标题 代码 <body><h1>一级标题</h1><h2>二级标题</h2><h3>三级标题</h3><h4>四级标题</h4><h5>五级标题</h5>…

视频提取gif的手机端操作方法?看看这个就会了

Gif图片是一种非常流行的格式&#xff0c;广泛应用于社交媒体、网络宣传单等。它们能够轻松的吸引大众的注意力&#xff0c;在使用聊天软件的时候我们常常会使用gif动图表情包来调节聊天氛围。Gif动图比普通的图片有趣&#xff0c;也比视频的体积要小。我们想要通过手机来把视频…

从需求到实现:能源软件服务商如何量身定制企业解决方案

能源行业需要数字化转型的原因主要有以下几点&#xff1a;首先&#xff0c;数字化技术可以提高生产效率和安全性&#xff0c;通过实时监控和智能调度降低事故风险&#xff0c;并实现远程控制和自动化生产。其次&#xff0c;数字化转型有助于推动能源行业的创新发展&#xff0c;…

GPT-4o正式发布;零一万物发布千亿参数模型;英国推出AI评估平台

OpenAI 正式发布 GPT-4o 今天凌晨&#xff0c;OpenAI 正式发布 GPT-4o&#xff0c;其中的「o」代表「omni」&#xff08;即全面、全能的意思&#xff09;&#xff0c;这个模型同时具备文本、图片、视频和语音方面的能力&#xff0c;甚至就是 GPT-5 的一个未完成版。 并且&…

本地安装nvm,管理多版本node

先卸载本地的nodejs(14.16.1) 卸载的直接可以点击win10图标→设置→应用→应用和功能 卸载nodejs即可 2. 安装nvm&#xff0c;地址&#xff1a;https://github.com/coreybutler/nvm-windows/releases 安装目录时尽量不要出现特殊字符还有空格&#xff0c;否则会在nvm use xxx的…

HTML常用标签-列表标签

列表标签 有序列表 分条列项展示数据的标签, 其每一项前面的符号带有顺序特征 无序列表 分条列项展示数据的标签, 其每一项前面的符号不带有顺序特征 有序列表标签 ol无序列表标签 ul列表项标签 li代码 <!-- 有序列表 --><ol><li>JAVA</li><li>前…

python的文件处理

文件分为文本文件和二进制文件&#xff1a; 我这样理解&#xff1a;就是电脑上用记事本打开我们可以看懂的文件就是文本文件&#xff0c;比如docx&#xff0c;txt&#xff0c;cpp&#xff0c;json&#xff0c;md等。直接点开看不懂的就是二进制文件&#xff0c;比如png&#xf…

考研数学|强化《660》+《880》这样刷,太丝滑了❗️

660题880题需要大概两个月才能做完 660题和880题都是很高质量的题集&#xff0c;所以做起来一点也不轻松。 每年都会有学生暑假两个月只做了一本660题的情况&#xff0c;因为题目实在是太难&#xff0c;有点做不下去的感觉。 不过不要担心&#xff0c;暑假就是刷题发现问题的…

k8s 网络组件详细 介绍

目录 一 k8s 有哪些网络组件 二 k8s 网络概念 1&#xff0c; k8s 三种网络 2&#xff0c;K8S 中 Pod 网络通信 2.1 Pod 内容器与容器之间的通信 2.2 同一个 Node 内 Pod 之间的通信 2.3 不同 Node 上 Pod 之间的通信 三 Flannel 网络组件 1&#xff0c;Flannel …

C++干货--引用

前言&#xff1a; C的引用&#xff0c;是学习C的重点之一&#xff0c;它与指针的作用有重叠的部分&#xff0c;但是它绝不是完全取代指针(后面我们也会简单的分析)。 引用的概念&#xff1a; 引用 不是新定义一个变量 &#xff0c;而 是给已存在变量取了一个别名 &#xf…

spring boot 线程池的应用

文章目录 引言I 配置线程池II 封装线程池任务执行器2.1 唯一性标识2.2 LogFilter:设置request_id2.3 logback使用request_idIII 检测线程池引言 SpringBootApplication启动类上需要加入注解@EnableAsync或者在配置类上使用 应用场景:封装线程池任务执行器:在任务提交时,会…

学习uni-app期间css样式的导入、单位属性和ui工具关系

css单位属性 css中单位有&#xff1a; px &#xff1a;屏幕像素 vw&#xff1a;屏幕宽度 vh &#xff1a;屏幕高度 rpx &#xff1a;响应式 px&#xff0c;一种根据屏幕宽度自适应的动态单位。以 750 宽的屏幕为基准&#xff0c;750rpx 恰好为屏幕宽度。屏幕变宽&#xff0c;rp…

【转载】【亲测可用】Ubuntu18.04安装VTK-8.2.0

这篇文章转载大部分都参考自下面的链接&#xff0c;注意cmake的版本&#xff0c;如果版本不对是编译失败的 https://blog.csdn.net/qq_42257666/article/details/124574029?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171566768016800182751339%2522%252C%2522…

Power query与Excel的区别,优势?

Power Query是Microsoft Excel的一个强大数据导入、转换和自动化的插件工具&#xff0c;它在Excel 2010之后的版本中被发布出来&#xff0c;随着时间的发展&#xff0c;功能不断增强。 以下是Power Query的一些优势以及它与Excel传统数据处理方式的区别和一些令人印象深刻的功…

HTML(基础语法)(1)

标题标签 h1~h6双标签 h1一个网页只能用一次 其他可多次使用 段落标签 p 换行<br> 水平线<hr> 文本格式化标签 加粗 strong /b 倾斜 em/i 下划线 ins/u 删除线 del/s 图片标签 <img src"图片"> src用于指定图片的位置和名称 ./开头&…

【选型推荐】洁净室( 区) 悬浮粒子的测试方法及仪器选型

环境监测承担着环境污染控制措施有效性的评判者的角色。其本身不是一个控制措施&#xff0c;环境监测本身并不能够改变环境指标&#xff0c;降低污染。一个有效的环境监测体系是能反映洁净区内的粒子和微生物的真实水平。确认环境是否满足法规的要求&#xff0c;同时给予污染控…

【Java 演示灵活导出数据】

演示灵活导出数据 &#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;【小吴小吴bug全无开通公众号】关注公众号获取第一时间博客动态 背景今天临时起兴打开稀土掘金导航栏看到页面推广gitee项目恰巧最近也在学习python了解到python爬虫很厉害&…

java基础之特殊类枚举

一、什么是枚举 枚举是JDK5新增特性&#xff0c;用来表示一组常量值&#xff0c;比如一年由四个季节&#xff0c;一年中有12个月份&#xff0c;、订单有未付款​、已付款、已发货、已收货状态等。 二、枚举的好处 ​用枚举来表示组常量值&#xff0c;可以避免非法值。 publ…

# 从浅入深 学习 SpringCloud 微服务架构(十八)

从浅入深 学习 SpringCloud 微服务架构&#xff08;十八&#xff09; 一、开源配置中心 Apollo&#xff1a;概述 1、开源配置中心 Apollo Apollo -A reliable configuration management system Apollo(阿波罗)是携程框架部门研发的分布式配置中心&#xff0c;能够集中化管理…

一篇文章告诉你:通信网优比计算机岗位好在哪?

据优橙2023年就业人员专业分布统计&#xff0c;通信专业学员占比32.7%&#xff0c;非通信专业学员占比64.8%&#xff0c;其他占比2.5%。 可见从事网优的学员中大部分为非通信专业。而非通信专业中72%的学生在学习通信网优还是计算机专业中&#xff0c;选择了通信网优。 为什么越…