单例设计模式Singleton

news/发布时间2024/5/15 14:16:55

1.模式定义

保证一个类只有一个实例,并且提供一个全局访问点

2.应用场景

重量级的对象,不需要多个实例,如线程池,数据库连接池。

2.1 源码中的应用

// Spring & JDK
java.lang.Runtime
org.springframework.aop.framework.ProxyFactoryBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
org.springframework.core.ReactiveAdapterRegistry
// Tomcat
org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
// 反序列化指定数据源
java.util.Currency

3.实现方式

3.1 懒汉模式

延迟加载, 只有在真正使用的时候,才开始实例化。
1)线程安全问题
2)double check 加锁优化
3)编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化
的实例,可以通过添加volatile 关键字进行修饰,
对于volatile 修饰的字段,可以防止指令重排。
public class LazySingletonTest {public static void main(String[] args) {
//        LazySingleton singleton = LazySingleton.getInstance();
//        LazySingleton singleton1 = LazySingleton.getInstance();
//        System.out.println(singleton == singleton1);Thread thread = new Thread(()->{LazySingleton s1 = LazySingleton.getInstance();System.out.println(s1);});thread.start();Thread thread2 = new Thread(()->{LazySingleton s1 = LazySingleton.getInstance();System.out.println(s1);});thread2.start();}
}class LazySingleton{private volatile static LazySingleton singleton = null;private LazySingleton(){}public static LazySingleton getInstance(){// synchronized 不建议修饰在方法上,因为方法上每次调用都需要加锁,性能低if (singleton == null) {synchronized (LazySingleton.class){if (singleton == null) {singleton = new LazySingleton();//字节码// 1.分配空间// 2.初始化// 3.引用赋值// 初始化和引用赋值可以不分先后进行}}}return singleton;}
}

3.2.饿汉模式

类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于jvm
类加载机制,保证实例的唯一性(初始化过程只会执行一次)及线程安
全(JVM以 同步 的形式来完成类加载的整个过程)。
类加载过程:
1,加载二进制数据到内存中, 生成对应的Class数据结构,
2,连接: a. 验证, b.准备(给类的静态成员变量赋 默认值 ),c.解析
3, 初始化 : 给类的静态变量赋 初值
只有在真正使用对应的类时,才会触发初始化 如( 当前类是启动类即
main函数所在类,直接进行new 操作,访问静态属性、访问静态方
法,用反射访问类,初始化一个类的子类等.)
class HungerSingleton {private static HungerSingleton singleton = new HungerSingleton();private HungerSingleton() {}public static HungerSingleton getInstance() {return singleton;}
}

3.3 静态内部类

1).本质上是利用类的加载机制来保证线程安全
2).只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一
种形式。
class InnerClassSingleton {private InnerClassSingleton() {}private static class InnerClassHandle {private static InnerClassSingleton singleton = new InnerClassSingleton();}public static InnerClassSingleton getInstance(){return InnerClassHandle.singleton;}
}

3.4 反射攻击实例

静态内部类防止反射破坏

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

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

相关文章

Flutter GLSL - 肆 | 从条纹到马赛克

theme: cyanosis Flutter & GLSL 系列文章: 《Flutter & GLSL - 壹 | Shader 让绘制无限强大》《Flutter & GLSL - 贰 | 从坐标到颜色》《Flutter & GLSL - 叁 | 变量传参》《Flutter & GLSL - 肆 | 从条纹到马赛克》 案例代码开源地址 【skele…

C++学习之list容器

C++ list基本概念 在C++中,std::list是一个双向链表(doubly linked list)容器,它包含在 <list> 头文件中。下面是一些关于C++ std::list的基本概念: 双向链表结构:std::list是由多个节点组成的双向链表结构,每个节点包含数据元素和指向前一个节点和后一个节点的指…

树-王道-复试

树 1.度&#xff1a; 树中孩子节点个数&#xff0c;所有结点的度最大值为 树的度 2.有序树&#xff1a; 逻辑上看&#xff0c;树中结点的各子树从左至右是有次序的&#xff0c;不能互换。 **3.**树的根节点没有前驱&#xff0c;其他节点只有一个前驱 **4.**所有节点可有零个或…

wondows10用Electron打包threejs的项目记录

背景 电脑是用的mac&#xff0c;安装了parallels desktop ,想用electron 想同时打包出 苹果版本和windows版本。因为是在虚拟机里安装&#xff0c;它常被我重装&#xff0c;所以记录一下打包的整个过程。另外就是node生态太活跃&#xff0c;几个依赖没记录具体版本&#xff0…

Flink中的双流Join

1. Flink中双流Join介绍 Flink版本Join支持类型Join API1.4innerTable/SQL1.5inner,left,right,fullTable/SQL1.6inner,left,right,fullTable/SQL/DataStream Join大体分为两种&#xff1a;Window Join 和 Interval Join 两种。 Window Join又可以根据Window的类型细分为3种…

Kotlin 进阶版 协程

kotlin是协程的一种实现 Dispatchers.IO&#xff1a;适用于执行磁盘或网络 I/O 操作的调度器&#xff0c;例如文件读写、网络请求等。在 Android 中&#xff0c;Dispatchers.IO 会使用一个专门的线程池来处理这些操作&#xff0c;以防止阻塞主线程。 Dispatchers.Main&#xf…

RabbitMQ鉴权设计以及相关探讨

文章目录 1. rabbitmq的鉴权设计2. rabbitmq鉴权应用范围3. rabbitmq鉴权的常用方法3.1 用户管理3.2 角色管理3.3 权限管理 4. 默认鉴权4.1 默认用户4.2 默认角色 5. 参考文档 鉴权&#xff0c;分别由鉴和权组成 鉴&#xff1a; 表示身份认证&#xff0c;认证相关用户是否存在…

如何使用逻辑回归处理多标签问题?

逻辑回归处理多分类 1、背景描述2、One vs One3、One VS Rest4、从Sigmoid到Softmax的推导 1、背景描述 逻辑回归本身只能用于二分类问题&#xff0c;如果实际情况是多分类的&#xff0c;那么就需要对模型进行一些改动。下面介绍三种常用的将逻辑回归用于多分类的方法 2、One …

使用openai-whisper实现语音转文字

使用openai-whisper实现语音转文字 1 安装依赖 1.1 Windows下安装ffmpeg FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。 # ffmpeg官网 https://ffm…

【Crypto | CTF】BUUCTF RSA2

天命&#xff1a;密码学越来越难了&#xff0c;看别人笔记都不知道写啥 天命&#xff1a;莫慌&#xff0c;虽然我不会推演法&#xff0c;但我可以用归纳法 虽然我不知道解题的推演&#xff0c;但我可以背公式啊哈哈哈 虽然我不会这题&#xff0c;但是我也能做出来 公式我不知…

Qt事件过滤器

1. 事件过滤器 void QObject::installEventFilter(QObject *filterObj) bool eventFilter(QObject *obj, QEvent *event); filterObj表示事件筛选器对象&#xff0c;它接收发送到此QObject对象&#xff08;安装事件过滤器的部件对象&#xff09;的所有事件。筛选器可以停止事件…

LeetCode JS专栏刷题笔记(二)

一、前言 LeetCode - JavaScript 专栏刷题笔记第二篇。 第一篇刷题笔记详见&#xff1a;LeetCode JS专栏刷题笔记&#xff08;一&#xff09; 二、算法题目 1. 复合函数 LeetCode地址&#xff1a;2629. 复合函数 请你编写一个函数&#xff0c;它接收一个函数数组 [f1, f2, …

SQL-FEFT JOIN (拼接表)

语法 SELECT column_name(s) FROM table1 LEFT JOIN table2 ON table1.column_nametable2.column_name; 按照一定规则&#xff0c;将表table1和表table2拼接起来。 例&#xff1a; Employees 表&#xff1a; ------------------------ | Column Name | Type | ------…

挑战!贪吃蛇小游戏的实现(3)

经过&#xff08;1&#xff09;&#xff08;2&#xff09;两篇文章的介绍&#xff0c;相信大家对该游戏的实现已经有了具体的思路&#xff0c;废话不多说&#xff0c;让我们开始实现相关的代码吧&#xff01; 1.游戏主逻辑 void test() {int ch 0;srand((unsigned int)time(NU…

【Linux系统化学习】动静态库 | 软硬链接

目录 硬链接和软链接 硬链接 软链接 动态库和静态库 静态库 静态库的生成 静态库的使用 将库打包和使用 动态库 动态库的生成 动态库的使用 库搜索路径 硬链接和软链接 硬链接 上篇文章我们说到真正找到磁盘上的文件并不是文件名&#xff0c;而是inode。其实在…

【Appium UI自动化】pytest运行常见错误解决办法

通过Appium工具录制代码在pycharm上运行报错&#xff1a; 错误一&#xff1a; 1.提示 setup() 方法运行 error failed 解决办法&#xff1a;未创建 init __ 方法&#xff0c;创建一个空的__init.py文件就解决了。 原因&#xff1a; 错误二&#xff1a; 2.运行代码&#xff…

解决SpringAMQP工作队列模型程序报错:WARN 48068:Failed to declare queue: simple.queue

这里写目录标题 1.运行环境2.报错信息3.解决方案4.查看解决之后的效果 1.运行环境 使用docker运行了RabbitMQ的服务器&#xff1a; 在idea中导入springAMQP的jar包&#xff0c;分别编写了子模块生产者publisher&#xff0c;消费者consumer&#xff1a; 1.在publisher中运行测试…

PostgreSQL 的实体化视图介绍

PostgreSQL 实体化视图提供一个强大的机制&#xff0c;通过预先计算并将查询结果集存储为物理表来提高查询性能。本教程将使用 DVD Rental Database 数据库作为演示例子&#xff0c;指导你在 PostgreSQL中创建实体化视图。 了解实体化视图 实体化视图是查询结果集的快照&…

【ECharts】调用接口获取后端数据的四种方法

使用eacharts做大屏&#xff0c;需要使用后端数据&#xff0c;下面的方法是自己试过有效的&#xff0c;有什么不对的&#xff0c;望各位大佬指点。 目录 方法一&#xff1a;在mounted中使用定时器调用eacharts方法&#xff08;定时器可以获取到data中的数据&#xff09; 方法…

【C++精简版回顾】7.析构函数

1.析构函数 class MM { public:MM() {}MM(const char* a) {name new char[strlen(a)1];strcpy(name, a);cout << name << endl;}~MM() {delete[] name;name nullptr;cout << "调用析构函数" << endl;} private:char* name; }; int main(…
推荐文章