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

2023-10-29 18:20

本文主要是介绍由一个单例模式引发的思考-holder类方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

最近在看《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类已经被加载过了,所以不用再次加载。

这篇关于由一个单例模式引发的思考-holder类方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/302501

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

【即时通讯】轮询方式实现

技术栈 LayUI、jQuery实现前端效果。django4.2、django-ninja实现后端接口。 代码仓 - 后端 代码仓 - 前端 实现功能 首次访问页面并发送消息时需要设置昵称发送内容为空时要提示用户不能发送空消息前端定时获取消息,然后展示在页面上。 效果展示 首次发送需要设置昵称 发送消息与消息展示 提示用户不能发送空消息 后端接口 发送消息 DB = []@ro

脏页的标记方式详解

脏页的标记方式 一、引言 在数据库系统中,脏页是指那些被修改过但还未写入磁盘的数据页。为了有效地管理这些脏页并确保数据的一致性,数据库需要对脏页进行标记。了解脏页的标记方式对于理解数据库的内部工作机制和优化性能至关重要。 二、脏页产生的过程 当数据库中的数据被修改时,这些修改首先会在内存中的缓冲池(Buffer Pool)中进行。例如,执行一条 UPDATE 语句修改了某一行数据,对应的缓

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素