单例模式深入解析(Java)

Java 单例模式:深度解析与应用 Java 单例模式是一种极为实用的设计模式,通过限制类的实例化次数为一次,并提供全局访问点,在资源管理、配置信息处理、线程池和日志记录等众多场景中都有着广泛的应用。本文详细介绍了饿汉式、懒汉式、双重检查锁定、静态内部类和枚举等多种单例模式的实现方式,深入分析了它们的线程安全性、懒汉式与饿汉式的区别以及应用场景。在实际开发过程中,开发人员需要依据具体的需求和场景,仔细权衡资源占用、线程安全和性能等多方面因素,从而选择最为合适的单例模式实现方式,以此构建高效、可靠的 Java 应用程序。 阅读详情

前言

相信各位对单例模式都不陌生,这已经是一个老生常谈的设计模式。之前我对于单例模式的理解仅仅停留在表面上,知道有几种,知道如何实现,知道大概的区别如何,但是其实单例模式还有很多不为人知的另一面,接下来我们就一起来看看。

单例模式的五种写法

方案一: 饿汉式

public class Singleton {   
    private static Singleton = new Singleton();
    private Singleton() {}
    public static getSignleton(){
        return singleton;
    }
}

方案二:懒汉式

public class Singleton {
    private static Singleton singleton = null;
    private Singleton(){}
    public static Singleton getSingleton() {
        if(singleton == null) singleton = new Singleton();
        return singleton;
    }
}

方案三:线程安全

public class Singleton {
    private static volatile Singleton singleton = null;
 
    private Singleton(){}
 
    public static Singleton getSingleton(){
        synchronized (Singleton.class){
            if(singleton == null){
                singleton = new Singleton();
            }
        }
        return singleton;
    }    
}

方案四:双重校验锁

public class Singleton {
    private static volatile Singleton singleton = null;
 
    private Singleton(){}
 
    public static Singleton getSingleton(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }    
}

方案五:静态内部类

public class Singleton {
    private static class Holder {
        private static Singleton singleton = new Singleton();
    }
 
    private Singleton(){}
 
    public static Singleton getSingleton(){
        return Holder.singleton;
    }
}

方案六:枚举

public enum Singleton {
    INSTANCE;
}

单例模式的线程安全

方案一和方案二,非线程安全;
方案三和方案四,将唯一的实例进行判空操作,以及实例化的部分进行了synchronized进行加锁,实现了部分线程安全,那么还有什么隐患呢?那就是指令重排优化。
这里我们着重讲一下volatile修饰符,

volatile

volatile,有两层含义。第一层,可见性。第二层,防止重排序。
在类加载的过程中,分为以下几个步骤:

  • 分配内存空间
  • 初始化
  • 将 singleton 对象指向分配的内存地址

在没有volatile修饰之前,初始化和指向分配内存地址的执行顺序不可预测,那么就会导致一个问题:

在线程A正在进行类加载的过程中,恰好先执行了指向分配内存地址这一步,此时singleton已经不为null,但是由于还没有初始化,所以singleton也不能算是一个正常的实例对象。这个时候切换到线程B,由于singleton此时已经不是null,所以会直接返回,拿去调用一些方法,这个时候就会抛出异常。

volatile是如何保证线程安全的呢?

那么volatile的出现保证了在类加载的过程中,先进行初始化,再将singleton对象指向分配的内存地址。
在线程A进行类加载的时候,假如执行到初始化这一步,线程B的请求过来,由于此时singleton是null的,所以会被synchronized同步锁锁住,直到singleton实例化成功,再进行调用。

方案五,将实例放置在静态内部类中,静态内部类只会被加载一次,实现了线程安全。
方案六,枚举的内部实现自动帮我们实现了线程安全。

单例模式的反射安全

针对除了枚举单例以外的方案来说,为什么会有反射不安全呢?如果用户通过类的反射去调用构造函数,获取实例,那么我们的单例就不是真正意义上的单例模式了,那么如何解决这个问题呢?

在构造函数中,对singleton判空,如果非空,那我们就抛出异常,防止其反射调用。
【枚举自带防止反射强行调用的构造器】

单例模式的序列化安全

针对singleton实例的序列化和反序列化得到的对象是新的对象,那么这样就破坏了singleton的唯一性。
那么为什么在序列化的过程中会生成新的对象呢?
因为序列化会通过反射调用无参构造函数创建一个新的对象,如何避免呢?我们就回到了上一个问题,怎么去规避反射调用singleton的构造函数。
【枚举单例实现了自动序列化机制,防止了反序列化的时候创建新的对象】

总结

单例的四大要点:

  • 线程安全
  • 反射安全
  • 序列化与反序列化安全
  • 延迟加载

推荐阅读

为什么枚举单例的内部实现能保证线程安全以及序列化安全?

从ATE到ATPG:基于Scan Chain的芯片制造缺陷定位实战解析 本文深入解析了从ATE到ATPG的芯片制造缺陷定位实战技术,重点介绍了Scan Chain的工作原理、异步复位触发器处理技巧以及Design Compiler中的DFT实现方法。通过实际案例展示了如何利用ATE测试数据和ATPG工具进行精确的缺陷定位,并分享了提升测试覆盖率和优化测试成本的专业技巧,为芯片测试工程师提供了宝贵的实战经验。 阅读详情

相关推荐

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

m0_72224305的博客 4305

Java单例模式深度解析

单例模式(Singleton Pattern)是 Java 中最经典的设计模式之一,用于确保一个类只有一个实例,并提供全局访问点。以下是深度解析,涵盖核心思想、实现方式、线程安全、反射/序列化漏洞及最佳实践。唯一性:确保类只有一个实例。全局访问:通过静态方法或静态变量提供全局访问入口。延迟加载(可选):在首次使用时创建实例,减少资源占用。 public class Singleton { private static final Singleton INSTANCE = new Singleton(

Vic10101的博客 1128

方差分解分析变量筛选与显著性计算

冗余分析(redundancy analysis,RDA)是一种回归分析结合主成分分析的排序方法,也是多响应变量(multiresponse)回归分析的拓展。在进行VPA时,首先就要对这些环境因子进行一个分类,然后在约束其它类环境因子的情况下,对某一类环境因子进行排序分析,这种分析也成为偏分析,即partialRDA。在地球环境科学的实际应用中,可以基于VPA结果得出不同类型的环境因素(如何气候、土壤性质以及植物)对生物群落组成(如植被丰度,微生物群落)的解释程度。对于由或创建的排序对象,函数。

wlh2067的博客 2519

【java】深度解析单例模式

前言 关于单例模式,请看菜鸟教程中的定义: 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 注意 单例类只能有一个实例。 单例类必须...

weixin_43148189的博客 484

SpringBoot Redis入门(一)——redis、Lettuce、Redisson使用

Lettuce是SpringBoot自带的Redis客户端,性能比Redis要好, 是线程安全的,支持同步编程,异步编程,响应式编程,自动重新连接,主从模式,集群模块,哨兵模式Redisson 是一个在 Redis 的功能基础上实现的 Java 驻内存数据网格客户端。实现了分布式和可扩展的 Java 数据结构,提供很多分布式相关操作服务,例如分布式锁,分布式集合,可通过 Redis 支持延迟队列。

朗朗的博客 3833

Dynamics CRM证书更换

  Dynamics CRM产品一般有两种认证方式。第一种是基于声明的内部访问也就是无证书单纯用账号密码验证。第二种就是联合身份认证,需要安装网站证书。   对于联合身份认证的情况因为需要安装证书,而且证书是有一个一年的有效期,所以运维人员每年都需要进行证书更换的操作。以下就是更换证书的方法及过程。 证书根据申请方式一般也分两种,第一种是自建证书,这种证书是没有机构认证的所以安装上之后网站因为没...

bzpfly的博客 877

Java单例模式全解析:饿汉、懒汉与双重校验锁

本文详细介绍了Java编程中的单例模式,探讨了其基本概念、三种常见实现方式(饿汉模式、懒汉模式和双重校验锁模式)及其各自的原理、优缺点和应用场景。

小L的博客 1798

BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversarial Network(2018,妆容迁移)

论文下载地址:BeautyGAN | Proceedings of the 26th ACM international conference on Multimedia 目的:在实例级实现化妆图像和非化妆图像的妆容迁移 方法:全局域集损失和本地实例级损失合并到一个双输入/输出对抗生成网络。步骤:使用一对鉴别器将非化妆面传输到化妆域,鉴别器从域的真实样本中分辨出生成的图像。在域集迁移的基础上,采用基于不同人脸区域的像素级直方图损失来实现实例级迁移。为了保持人脸的一致性和消除伪影,在总体目标函数中加入了.

weixin_53965540的博客 663

Java单例模式的实现方式解析

本文详细介绍了Java单例模式的多种实现方式,包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举类等,并对各种实现方式的原理、优缺点和适用场景进行了深入分析。在实际开发中,应根据具体需求选择合适的单例实现方式。一般情况下,静态内部类和枚举类是最推荐的实现方式,它们既简单又安全,能满足大多数应用场景的需求。单例模式作为一种常用的设计模式,不仅能有效节约系统资源,还能确保数据的一致性。

weixin_56018532的博客 882

从PHY芯片看工业网络精准时钟:IEEE 1588v2(PTP)协议实现与选型指南

本文深入解析了工业网络中IEEE 1588v2(PTP)协议的实现与PHY芯片选型要点。通过对比KG7101、RTL8211F等芯片的关键参数,揭示硬件时间戳对纳秒级时钟同步的决定性作用,并提供PTP网络设计中的拓扑布局与配置优化技巧,助力工业自动化场景实现精准时间同步。

weixin_42628688的博客 500

固定翼飞行器建模(一)——六自由度动力学

前两期文章讲完了气动力和气动力矩的模型,本期将来讲解一下六自由度部分的动力学与运动学方程。

2302_80148937的博客 1万+

Java单例模式:从实战到面试的深度解析

不加volatile可能导致步骤2和3重排序,其他线程可能拿到未初始化完成的对象。:防止指令重排序导致返回未初始化完成的对象。文章持续更新,可以微信搜一搜「

趁年轻,多去失败 777

避坑指南!YOLO26模型导出/推理常见问题,99%的开发者都踩过

版本锁定:Ultralytics=8.4.2、OpenVINO=2024.0.0、Python=3.10,版本不一致是80%问题的根源;参数对齐:训练/导出/推理的imgsz、归一化、坐标映射必须完全一致,差一步就出错;算子统一:避免自定义算子,优先用YOLO26原生算子(C3k2/PSABlock),确保推理引擎兼容;分步验证:导出后先校验ONNX/IR模型→单图片推理→RTSP流推理→72小时稳定性测试,一步过易踩坑;工业级测试。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 510

java设计模式深度解析与实践:单例模式

单例性:一个类在整个程序运行期间只能有一个实例存在。全局访问性:提供一个全局的访问点,使得其他类可以方便地获取这个唯一的实例。单例模式是一种非常实用的设计模式,在控制资源访问和全局协调方面具有显著优势。通过合理选择实现方式,可以有效避免资源浪费和线程安全问题。然而,在实际应用中,也需要注意单例模式的潜在缺陷,如过度耦合和难以测试等问题。在分布式系统中,实现单例模式则需要引入分布式锁等机制,以确保全局唯一性。希望本文能够帮助您全面理解单例模式的实现与应用,从而在实际开发中做出更明智的选择。

panqiangqiangqiang的博客 1239

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

深度解析 Java 单例模式

摘要:本文讲解了Java单例模式的核心概念与实现方式。单例模式确保类仅有一个实例,适用于资源共享、控制中心等场景。文章详细介绍了5种实现方法:1)饿汉式(线程安全但不延迟加载);2)懒汉式(线程不安全);3)双重检验锁(推荐,需volatile防指令重排);4)静态内部类(优雅延迟加载);5)枚举(最安全,天然防反射和序列化破坏)。最后分析了单例可能被反射和序列化破坏的情况及防御措施,推荐根据场景选择静态内部类或枚举实现。

2401_87808951的博客 764

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java 单例模式解析

所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在。就像是Java Web中的application,也就是提供了一个全局变量,用处相当广泛,比如保存全局数据,实现全局性的操作等。   1. 最简单的实现   首先,能够想到的最简单的实现是,把类的构造函数写成private的,从而保证别的类不能实例化此类,然后在类中提供一个静态的实例并能够返回给使用者。这样,使用者就可以...

龙行天下 151

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java深入解析:线程安全的单例模式实现

以上介绍了多种 Java 线程安全的单例模式实现方式,每种方式都有其独特的优势和适用场景。饿汉式简单直接,但可能造成资源浪费;懒汉式双重检查锁实现了性能与安全的平衡,但需要正确使用 volatile 关键字;静态内部类借助 JVM 实现优雅的线程安全与延迟初始化;枚举方式简洁高效,尤其适合处理序列化场景。​在实际项目中,开发者应根据具体需求选择合适的单例模式实现方式。如果对资源消耗不敏感,追求简单性,饿汉式是不错的选择;若需要延迟初始化且注重性能,懒汉式双重检查锁或静态内部类更为合适;

2301_77880989的博客 1344

java单例模式解析

1. 前言 单例模式是项目中经常使用的一种设计模式,其特点是整个项目中,只会有一个实例运行。想要创建一个单实例对象,需要以下几个条件: 1)单例类只能有一个实例。 2)单例类必须自己创建自己的唯一实例。 3)单例类必须给所有其他对象提供这一实例。 为了不让外部可以随意的创建对象实例,我们需要私有化构造方法,然后从类的内部进行对象的实例化。对象实例化之后,我们可以通过静态变量来存储这个对象, 创建单例模式有两种方式,一种是饿汉式,一种是懒汉式,下面会针对这两种方式进行讲解 2.饿汉式 饿汉式顾名思义,实例

孙应路的博客 315

Java单例模式解析

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

manzubaolong的博客 199

java 单例模式解析

1.介绍与样例 (1)懒汉模式 (2)饿汉模式 单例模式的结构与实现 2.为何使用private,static,final? 单例模式中为什么要使用final和static? 2.懒汉模式线程不安全,如何解决? 廖雪峰网站-单例模式 ...

技术改变世界 229

Java中的单例模式解析

单例模式(Singleton Pattern)是一种创建型设计模式,​。在Java中广泛应用于配置管理、线程池、数据库连接池等场景。

2401_89496570的博客 348

Java单例模式深度解析与最佳实践

单例模式(Singleton Pattern)是一种创建型设计模式,通过限制类实例化次数为一次,实现全局唯一访问点的目标。主要使用场景:①配置管理类(如数据库连接配置)② 资源控制器(线程池/连接池管理)③ 日志记录器(避免多实例写日志冲突)

weixin_60006489的博客 502

java单例模式构造器初始化_解析单例模式

特点:1.构造函数不外放,一般都是private2.通过暴露一个public的静态方法或者枚举来返回一个单例对象3.在多线程环境下面,确保单例类对象有且只有一个4.确保单例类对象再反序列化时候不会重新构建对象懒汉模式:public classSingleton{ private staticSingleton instance; //1.构造函数不对外开放privateSingle...

weixin_42502288的博客 624

Java开发中的设计模式单例模式的深入解析与实践

单例模式是一种创建型设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点来获取这个唯一实例。在Java开发中,单例模式的应用场景非常广泛,例如需要控制共享资源访问(如数据库连接池、线程池)、配置信息管理、日志记录器等。通过单例模式,可以避免因创建多个实例而导致的资源冲突、数据不一致等问题,同时也节约了系统资源。

JackySun_bo的博客 692
上一篇: Handler源码分析
下一篇: Enum源码解析
丸子哒哒哒
博客等级 码龄12年 31粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值