当前位置: 首页 > news >正文

【设计模式】 单例模式(单例模式哪几种实现,如何保证线程安全,反射破坏单例模式)

单例模式

作用:单例模式的核心是保证一个类只有一个实例,并且提供一个访问实例的全局访问点。

实现方式优缺点
饿汉式线程安全,调用效率高 ,但是不能延迟加载
懒汉式线程安全,调用效率不高,能延迟加载
双重检测锁在懒汉式的基础上解决并发问题
静态内部类线程安全,资源利用率高,可以延时加载
枚举单例线程安全,调用效率高,但是不能延迟加载

饿汉式

在类加载的时候立即实例化对象,实现的步骤是先私有化构造方法,对外提供唯一的静态入口方法

public class SingletonInstance1 {private byte[] b1 = new byte[1024*1024];private byte[] b2 = new byte[1024*1024];private byte[] b3 = new byte[1024*1024];// 声明此类型的变量,并实例化,当该类被加载的时候就完成了实例化并保存在了内存中private final static SingletonInstance1 instance = new SingletonInstance1();// 私有化所有的构造方法,防止直接通过new关键字实例化private SingletonInstance1(){}// 对外提供一个获取实例的静态方法public static SingletonInstance1 getInstance(){return instance;}
}

在类加载时直接创建对象可能会造成空间的浪费

懒汉式

public class SingletonInstance2 {// 声明此类型的变量,但没有实例化private static SingletonInstance2 instance = null;// 私有化所有的构造方法,防止直接通过new关键字实例化private SingletonInstance2(){}// 对外提供一个获取实例的静态方法public static SingletonInstance2 getInstance(){if(instance == null){// 当instance不为空的时候才实例化instance = new SingletonInstance2();}return instance;}
}

外部调用getInstance()方法时才会创建对象(判断对象是否存在),但是不能保证多线程并发的情况下的线程安全,所以就出现了双重检测锁模式

双重检测锁模式

public class SingletonInstance3 {// 声明此类型的变量,但没有实例化,防止指令重排private volatile static SingletonInstance3 instance;// 私有化所有的构造方法,防止直接通过new关键字实例化private SingletonInstance3(){}// 对外提供一个获取实例的静态方法public static SingletonInstance3 getInstance(){if(instance == null){synchronized (SingletonInstance3.class){if(instance == null){// 当instance不为空的时候才实例化instance = new SingletonInstance3();/*1.分配内存空间2.执行构造法法,初始化对象3.把这个对象指向这个空间如果不加volatile 会执行重排序 1 3 2*/}}}return instance;}
}

静态内部类

public class SingletonInstance4 {// 静态内部类public static class SingletonClassInstance{// 声明外部类型的静态常量public static final SingletonInstance4 instance = new SingletonInstance4();}// 私有化构造方法private SingletonInstance4(){}// 对外提供的唯一获取实例的方法public static SingletonInstance4 getInstance(){return SingletonClassInstance.instance;}
}

枚举

public enum EnumSingle {INSTANCE;public EnumSingle getInstance(){return INSTANCE;}
}

如何保证线程安全

推荐使用 静态内部类 或者 双重检测锁 配合volatile使用

反射破坏单例模式

代码如下

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class LazyMan {private static boolean jiamibiaozhi = false;  // 加密标志位// 私有化所有的构造方法,防止直接通过new关键字实例化private LazyMan(){synchronized (LazyMan.class){if(!jiamibiaozhi){  // 防止反射破坏单例jiamibiaozhi = true;}else {throw new RuntimeException("不能试图使用反射破坏异常");}}System.out.println(Thread.currentThread().getName() +"LazyMan");}// 声明此类型的变量,但没有实例化, volatile防止指令重排private volatile static LazyMan instance;// 对外提供一个获取实例的静态方法public static LazyMan getInstance(){if(instance == null){synchronized (LazyMan.class){if(instance == null){// 当instance不为空的时候才实例化instance = new LazyMan();/*1.分配内存空间2.执行构造法法,初始化对象3.把这个对象指向这个空间如果不加volatile 会执行重排序 1 3 2*/}}}return instance;}// 反射破环单列public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {// LazyMan lazyMan = LazyMan.getInstance();Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null); // 获取空参构造器declaredConstructor.setAccessible(true); // 暴力反射,设置权限,无视私有构造器LazyMan lazyMan1 = declaredConstructor.newInstance(); // 通过空参构造器创建对象LazyMan lazyMan2 = declaredConstructor.newInstance();System.out.println(lazyMan1);System.out.println(lazyMan2);}
}

反射不能破坏枚举,见源码
在这里插入图片描述

相关文章:

【设计模式】 单例模式(单例模式哪几种实现,如何保证线程安全,反射破坏单例模式)

单例模式 作用&#xff1a;单例模式的核心是保证一个类只有一个实例&#xff0c;并且提供一个访问实例的全局访问点。 实现方式优缺点饿汉式线程安全&#xff0c;调用效率高 &#xff0c;但是不能延迟加载懒汉式线程安全&#xff0c;调用效率不高&#xff0c;能延迟加载双重检…...

T-SQL语言的数据库交互

T-SQL语言的数据库交互 引言 随着信息技术的不断发展&#xff0c;数据库在各个行业中扮演着越来越重要的角色。数据库的有效管理和优化对于企业的数据安全、效率提升和决策支持至关重要。T-SQL&#xff08;Transact-SQL&#xff09;作为微软SQL Server的重要扩展语言&#xf…...

【Linux系统】Ext系列磁盘文件系统二:引入文件系统(续篇)

inode 和 block 的映射 该博文中有详细解释&#xff1a;【Linux系统】inode 和 block 的映射原理 目录与文件名 这里有几个问题&#xff1a; 问题一&#xff1a; 我们访问文件&#xff0c;都是用的文件名&#xff0c;没用过 inode 号啊&#xff1f; 之前总是说可以通过一个…...

慧集通(DataLinkX)iPaaS集成平台-业务建模之域

通过左侧导航菜单〖业务建模〗→〖域〗&#xff0c;进入该界面&#xff1b;在该界面可以查看到系统中已存在的域列表。 新建域 在慧集通平台中进入【业务建模】的【域】页面&#xff0c;点击【新建】按钮进入新建页面&#xff1b;输入编码&#xff0c;名称、模块以及对应数据类…...

【机器学习实战】kaggle 欺诈检测---使用生成对抗网络(GAN)解决欺诈数据中正负样本极度不平衡问题

【机器学习实战】kaggle 欺诈检测---如何解决欺诈数据中正负样本极度不平衡问题https://blog.csdn.net/2302_79308082/article/details/145177242 本篇文章是基于上次文章中提到的对抗生成网络&#xff0c;通过对抗生成网络生成少数类样本&#xff0c;平衡欺诈数据中正类样本极…...

android wifi framework与wpa_supplicant的交互

android frmework直接与wpa_supplicant进行交互&#xff0c;使用aidl或者hidl 二、事件 framework注册事件的地方&#xff1a; packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java class SupplicantStaIfaceCallbackImpl exte…...

初学stm32 --- flash模仿eeprom

目录 STM32内部FLASH简介 内部FLASH构成&#xff08;F1&#xff09; FLASH读写过程&#xff08;F1&#xff09; 闪存的读取 闪存的写入 内部FLASH构成&#xff08;F4 / F7 / H7&#xff09; FLASH读写过程&#xff08;F4 / F7 / H7&#xff09; 闪存的读取 闪存的写入 …...

使用C语言实现栈的插入、删除和排序操作

栈是一种后进先出(LIFO, Last In First Out)的数据结构,这意味着最后插入的元素最先被删除。在C语言中,我们可以通过数组或链表来实现栈。本文将使用数组来实现一个简单的栈,并提供插入(push)、删除(pop)以及排序(这里采用一种简单的排序方法,例如冒泡排序)的操作示…...

C语言程序环境和预处理详解

本章重点&#xff1a; 程序的翻译环境 程序的执行环境 详解&#xff1a;C语言程序的编译链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 #include 预处理指令 #undef 条件编译 程序的翻译环境和执行环…...

基于机器学习随机森林算法的个人职业预测研究

1.背景调研 随着信息技术的飞速发展&#xff0c;特别是大数据和云计算技术的广泛应用&#xff0c;各行各业都积累了大量的数据。这些数据中蕴含着丰富的信息和模式&#xff0c;为利用机器学习进行职业预测提供了可能。机器学习算法的不断进步&#xff0c;如深度学习、强化学习等…...

三种文本相似计算方法:规则、向量与大模型裁判

文本相似计算 项目背景 目前有众多工作需要评估字符串之间的相似(相关)程度&#xff1a;  比如&#xff0c;RAG 智能问答系统文本召回阶段需要计算用户文本与文本库内文本的相似分数&#xff0c;返回前TopK个候选文本。  在评估大模型生成的文本阶段&#xff0c;也需要评估…...

Python语言的计算机基础

Python语言的计算机基础 绪论 在当今信息技术飞速发展的时代&#xff0c;编程已经成为了一种必备技能。Python凭借其简洁、易读和强大的功能&#xff0c;逐渐成为初学者学习编程的首选语言。本文将以Python语言为基础&#xff0c;探讨计算机科学的基本概念&#xff0c;并帮助…...

Dify应用-工作流

目录 DIFY 工作流参考 DIFY 工作流 2025-1-15 老规矩感谢参考文章的作者,避免走弯路。 2025-1-15 方便容易上手 在dify的一个桌面上,添加多个节点来完成一个任务。 每个工作流必须有一个开始和结束节点。 节点之间用线连接即可。 每个节点可以有输入和输出 输出类型有,字符串,…...

02.02、返回倒数第 k 个节点

02.02、[简单] 返回倒数第 k 个节点 1、题目描述 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该节点的值。 2、题解思路 本题的关键在于使用双指针法&#xff0c;通过两个指针&#xff08;fast 和 slow&#xff09;&#xff0c;让 fast 指针比 slow 指针…...

Linux手写FrameBuffer任意引脚驱动spi屏幕

一、硬件设备 开发板&#xff1a;香橙派 5Plus&#xff0c;cpu&#xff1a;RK3588&#xff0c;带有 40pin 外接引脚。 屏幕&#xff1a;SPI 协议 0.96 寸 OLED。 二、需求 主要是想给板子增加一个可视化的监视器&#xff0c;并且主页面可调。 平时跑个模型或者服务&#xff0c;…...

怎么修复损坏的U盘?而且不用格式化的方式!

当你插入U盘时&#xff0c;若电脑弹出“需要格式化才能使用”提示&#xff0c;且无法打开或读取其中的数据&#xff0c;说明U盘极有可能已经损坏。除此之外&#xff0c;若电脑在连接U盘后显示以下信息&#xff0c;也可能意味着U盘出现问题&#xff0c;需要修复损坏的U盘&#x…...

语音技术在播客领域的应用(2)

播客是以语音为主&#xff0c;各种基于AI 的语音技术在播客领域十分重要。 语音转文本 Whisper Whisper 是OpenAI 推出的开源语音辨识工具&#xff0c;可以把音档转成文字&#xff0c;支援超过50 种语言。这款工具是基于68 万小时的训练资料&#xff0c;其中包含11.7 万小时的…...

【Linux】应用层自定义协议与序列化

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 应用层 &#x1f98b; 再谈 "协议"&#x1f98b; 网络版计算器&#x1f98b; 序列化 和 反序列化 二&#xff1a;&#x1f525; 重新理解 read、…...

深度学习中的张量 - 使用PyTorch进行广播和元素级操作

深度学习中的张量 - 使用PyTorch进行广播和元素级操作 元素级是什么意思&#xff1f; 元素级操作在神经网络编程中与张量的使用非常常见。让我们从一个元素级操作的定义开始这次讨论。 一个_元素级_操作是在两个张量之间进行的操作&#xff0c;它作用于各自张量中的相应元素…...

gitignore忽略已经提交过的

已经在.gitignore文件中添加了过滤规则来忽略bin和obj等文件夹&#xff0c;但这些文件夹仍然出现在提交中&#xff0c;可能是因为这些文件夹在添加.gitignore规则之前已经被提交到Git仓库中了。要解决这个问题&#xff0c;您需要从Git的索引中移除这些文件夹&#xff0c;并确保…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...