由一个单例模式引发的思考-holder类方式

news2024/11/24 19:29:14

前言:

最近在看《Java并发编程实践》,里面提到了一种实现单例模式的方式,并大致说明了机制,但仍不是很清晰,今日有空,查阅相关书籍,尝试解释其中道理。

单例模式:

单例模式是一种常用的软件设计模式,它用于确保一个类只有一个实例,并提供一个全局访问点。单例模式通常用于需要频繁实例化且实例化对象消耗较大的情况,例如数据库连接、线程池等。

单例模式的实现方式有多种,包括饿汉式、懒汉式、双重校验锁、静态内部类等。其中饿汉式是指在类加载时就已经实例化对象,懒汉式则是延迟实例化,双重校验锁则是利用volatile关键字和synchronized关键字来保证线程安全。

单例模式的优点是可以避免对资源的多重占用,减少内存开销,同时设置全局访问点,可以优化和共享资源的访问。但是单例模式也存在一些缺点,例如如果要扩展该单例类,除了修改原来的代码,没有第二种途径,违背开闭原则。

总之,单例模式是一种常用的软件设计模式,它可以提高程序的性能和效率,但需要注意线程安全和扩展性问题。

以上来自文心一言。

单例的实现:

一般有懒汉,饿汉,DCL(双检锁),枚举,还有本文的holder,详细对应代码,可自行网上查阅。

类加载时机:

关于在什么情况下需要开始类加载过程的第一个阶段“加载”,《Java虚拟机规范》中并没有进行 强制约束,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,《Java虚拟机规范》 则是严格规定了有且只有六种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):

1)遇到new、getstatic、putstatic或invokestatic这四条字节码指令时,如果类型没有进行过初始化,则需要先触发其初始化阶段。能够生成这四条指令的典型Java代码场景有:

        ·使用new关键字实例化对象的时候。

        ·读取或设置一个类型的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外) 的时候。

        ·调用一个类型的静态方法的时候。

2)使用java.lang.reflect包的方法对类型进行反射调用的时候,如果类型没有进行过初始化,则需 要先触发其初始化。

3)当初始化类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先 初始化这个主类。

5)当使用JDK 7新加入的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四种类型的方法句柄,并且这个方法句柄对应的类没有进行过初始化,则需要先触发其初始化。

6)当一个接口中定义了JDK 8新加入的默认方法(被default关键字修饰的接口方法)时,如果有 这个接口的实现类发生了初始化,那该接口要在其之前被初始化。

                                                  --  来自《深入理解Java虚拟机:JVM高级特性与最佳实践》

如果觉得难以理解以上,还可以参考下R大的回答:

书中的代码形式及解释:

书中代码:

由上文可知,在调用ResourceFactory的getResource方法时,首先会加载和初始化本身调用一个类型的静态方法的时候),然后会触发ResourceHolder类加载和初始化读取或设置一个类型的静态字段),再触发Resouce类的加载和初始化使用new关键字实例化对象的时候)。

书中的解释如下:

日常写Holder类的形式及解释:

日常写单例的时候可以下面这种方式:

public class Student{
    private Student() {
    }
   

    private static class Holder{
        public static Student stu = new Student();

    }

    public static Student getInstance() {
        return Holder.stu;
    }


}

Resource相当于Student,在书的例子中:当使用Student类的getInstance方法时,首先会触发Student的加载机制(静态方法),然后会触发Holder内部类的加载(静态变量)。由于Student类已经被加载过了,所以不用再次加载。

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

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

相关文章

队列(8.6)

目录 2.队列 2.1队列的概念及结构 2.2队列的实现 2.2.1初始化队列 2.2.2队尾入队列 2.2.3队头出队列 2.2.4获取队列头部元素 2.2.5 销毁队列 3.栈和队列面试题 225. 用队列实现栈 - 力扣(LeetCode) 232. 用栈实现队列 - 力扣(LeetC…

【送书福利-第二十一期】《ChatGPT进阶:提示工程入门》

😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号:程序员洲洲。 🎈 本文专栏:本文…

正点原子嵌入式linux驱动开发——Linux 多点电容触摸屏

随着智能手机的发展,电容触摸屏也得到了飞速的发展。相比电阻触摸屏,电容触摸屏有很多的优势,比如支持多点触控、不需要按压,只需要轻轻触摸就有反应。ALIENTEK的三款RGB LCD屏幕都支持多点电容触摸,本章就以ATK7016这…

Spring Cloud Alibaba Seata 实现 SAGA 事物

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案 Seata 官网:https://seata.io/zh-cn/ Spring Cloud Alibaba 官…

【Java网络原理】 六

本文主要介绍了网络层的IP协议/NAT机制/IPv6的由来以及在数据链路层涉及到的以太网协议和DNS域名解析系统 一.网络层 1.IP协议 各个字段所表示的含义 >4位版本号 用来表示IP协议的版本,现在只有两个版本IPv4 ,IPv6 >4位首部长度 IP报头可变&…

【自然语言处理】【长文本处理】RMT:能处理长度超过一百万token的Transformer

相关博客 【自然语言处理】【长文本处理】RMT:能处理长度超过一百万token的Transformer 【自然语言处理】【大模型】MPT模型结构源码解析(单机版) 【自然语言处理】【大模型】ChatGLM-6B模型结构代码解析(单机版) 【自然语言处理】【大模型】BLOOM模型结构源码解析(…

AI直播换脸——DeepFaceLab 3.0模型训练与微调

前言 DeepFaceLab是一种基于深度学习的人脸合成和转换工具。它使用了深度神经网络来分析和修改图像中的人脸部分,可以实现将一个人的脸部特征应用到另一个人的照片上,或者进行面部表情、年龄、性别等特征的变换。 DeepFaceLab具备一系列核心功能&#x…

Matplotlib详解(plt 和ax分别是什么)

Matplotlib中的plt 和 ax 分别是什么? 概念引入两种绘图方式的区别subplot 绘制Matplotlib 常见组件设置整理4.1 设置显示中文字体4.2 设置标题4.3 边框的显示问题4.4 图例设置(legend)4.5 图形与边框之间的留白控制4.6 设置双坐标轴4.7 坐标…

Java毕业设计 SpringBoot 新能源充电桩管理系统

Java毕业设计 SpringBoot 新能源充电桩管理系统 SpringBoot 新能源充电桩管理系统 功能介绍 管理员 登录 验证码 注册 系统用户管理 普通用户管理 通知公告管理 留言管理 充电站管理 充电桩管理 充电桩预约 充电管理 订单管理 修改密码 普通用户 登录 修改个人资料 通知公告…

椭圆曲线在SM2中的应用(三)

一、SM2加密运算 1.1加密原始数据 SM2加密运算首先是用户A对数据加密,用户A拥有原始数据 椭圆曲线系统参数长度为klen比特的消息M公钥Pb椭圆曲线系统参数,已经在 椭圆曲线参数(二)中详细介绍;M就是需要加密消息,长度为klen; 1.1.1 公钥Pb的计算方式 公钥Pb=dBG,其中…

elasticsearch一些重要的配置参数

先看一下官网给我们提供的全部的参数配置项 官网地址 官方文档链接:注意版本是8.1Configuring Elasticsearch | Elasticsearch Guide [8.1] | Elastic​编辑https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html 重要(基本…

40.弗洛伊德(Floyd)算法

概述 我们此前拆解过迪杰斯特拉(Dijkstra)算法,与它一样,弗洛伊德(Floyd)算法也是用于寻找给定的加权图中顶点间最短路径的算法。该算法是1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特弗洛伊德及…

【Linux】centos安装配置及远程连接工具的使用

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《微信小程序开发实战》。🎯&#x1f3a…

私有云:【12】使用connention托管虚拟桌面

私有云:【12】使用connention托管虚拟桌面 1、使用connention托管虚拟桌面 1、使用connention托管虚拟桌面 使用cloudadmin用户登录connection服务器 登录connection客户端 创建桌面池 选择手动桌面池 选择vcenter虚拟机 选择vcenter.test.com 按如下选择下一步 设…

贝锐蒲公英旁路模式异地组网,不改动网络实现企业分部与总部互通

Micheal是一家快递公司的IT运维人员,因公司业务发展迅速,新增网点的速度非常快,各网点需将每天的数据都上传到总部服务器,及平时需要向总部服务器查询一些数据,总部的主路由是一台带有防火墙功能的企业路由&#xff0c…

共用体/联合体 的引入

概念 由一系列具有相同数据类型或者不同数据类型的数据组成的集合,数据互斥关系,共用体所有的成员共同使用一份内存空间,其中空间的大小是按照共用体成员中所占的最大的内存空间的成员的空间进行分配,即同一个内存空间存放类型不…

【PyQt学习篇 · ⑤】:QWidget - 鼠标操作

文章目录 鼠标形状设置常用鼠标形状设置自定义鼠标形状 重置形状获取鼠标鼠标跟踪鼠标跟踪案例 鼠标形状设置 常用鼠标形状设置 在PyQt中,QWidget类提供了设置鼠标形状的功能。可以使用setCursor()方法来更改QWidget及其子类的鼠标形状。该方法接受一个Qt.CursorS…

idea的设置

1.设置搜索encoding,所有编码都给换为utf-8 安装插件 eval-reset插件 https://www.yuque.com/huanlema-pjnah/okuh3c/lvaoxt#m1pdA 设置活动模板,idea有两种方式集成tomcat,一种是右上角config配置本地tomcat,一种是插件,如果使用插件集成,则在maven,pom.xml里面加上tomcat…

【uniapp】uniapp实现input输入显示数字键盘:

文章目录 一、官网文档:二、文档:三、效果:【1】number:iPhone原生数字键盘不显示小数点【2】digit:【3】digit和inputmode: 一、官网文档: input | uni-app官网 二、文档: 三、效果…

深度学习中Transformer的简单理解

Transformer 网络结构 Transformer也是由编码器和解码器组成的。 每一层Encoder编码器都由很多层构成的,编码器内又是self-attention和前馈网络构成的。Self-attention是用来做加权平均,前馈网络用来组合。 但是decoder有点不同,多了一层En…