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

news2025/4/6 8:15:35

单例模式

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

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

饿汉式

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

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);

    }
}

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

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

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

相关文章

【漏洞预警】FortiOS 和 FortiProxy 身份认证绕过漏洞(CVE-2024-55591)

文章目录 一、产品简介二、漏洞描述三、影响版本四、漏洞检测方法五、解决方案 一、产品简介 FortiOS是Fortinet公司核心的网络安全操作系统&#xff0c;广泛应用于FortiGate下一代防火墙&#xff0c;为用户提供防火墙、VPN、入侵防御、应用控制等多种安全功能。 FortiProxy则…

记录一次 centos 启动失败

文章目录 现场1分析1现场2分析2搜索实际解决过程 现场1 一次断电,导致 之前能正常启动的centos 7.7 起不来了有部分log , 关键信息如下 [1.332724] XFS(sda3): Internal error xfs ... at line xxx of fs/xfs/xfs_trans.c [1.332724] XFS(sda3): Corruption of in-memory data…

关于vite+vue3+ts项目中env.d.ts 文件详解

env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示&#xff0c;特别是在使用一些特定于 Vite 的功能时&#xff08;如 import.meta.env&#xff09;。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…

虚拟专用网VPN的概念及实现VPN的关键技术

虚拟专用网VPN通过建立在公共网络上的重要通道(1分),实现远程用户、分支机构、业务伙伴等与机构总部网络的安全连接&#xff0c;从而构建针对特定组织机构的专用网络&#xff0c;实现与专用网络类似的功能&#xff0c;可以达到PN安全性的目的&#xff0c;同时成本相对要低很多(…

将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(1)

问题 项目里使用了 AzureBlob 存储了用户上传的各种资源文件&#xff0c;近期 AzureBlob 的流量费用增长很快&#xff0c;想通过分析Blob的日志&#xff0c;获取一些可用的信息&#xff0c;所以有了这个需求&#xff1a;将存储账户的日志&#xff08;读写&#xff0c;审计&…

X-12-ARIMA:季节性调整(Seasonal Adjustment)的强大工具,介绍数学原理

X-12-ARIMA&#xff1a;季节性调整的强大工具 在经济学、金融学以及各类统计数据分析中&#xff0c;季节性调整&#xff08;Seasonal Adjustment&#xff09;是一个至关重要的步骤。许多经济指标&#xff0c;如GDP、失业率和零售销售数据等&#xff0c;往往会受到季节性因素的…

.netframwork模拟启动webapi服务并编写对应api接口

在.NET Framework环境中模拟启动Web服务&#xff0c;可以使用几种不同的方法。一个常见的选择是利用HttpListener类来创建一个简单的HTTP服务器&#xff0c;或者使用Owin/Katana库来自托管ASP.NET Web API或MVC应用。下面简要介绍Owin/Katana示例代码。这种方法更加灵活&#x…

网络安全构成要素

一、防火墙 组织机构内部的网络与互联网相连时&#xff0c;为了避免域内受到非法访问的威胁&#xff0c;往往会设置防火墙。 使用NAT&#xff08;NAPT&#xff09;的情况下&#xff0c;由于限定了可以从外部访问的地址&#xff0c;因此也能起到防火墙的作用。 二、IDS入侵检…

免费送源码:Java+ssm+MySQL 基于PHP在线考试系统的设计与实现 计算机毕业设计原创定制

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对在线考试等问题&#xff0c;对如何通过计算…

html中鼠标位置信息

pageX&#xff1a;鼠标距离页面的最左边的距离&#xff0c;包括滚动条的长度。clientX&#xff1a;鼠标距离浏览器视口的左距离&#xff0c;不包括滚动条。offsetX&#xff1a;鼠标到事件源左边的距离。movementX&#xff1a;鼠标这次触发的事件的位置相对于上一次触发事件的位…

光谱相机的光谱分辨率可以达到多少?

多光谱相机 多光谱相机的光谱分辨率相对较低&#xff0c;波段数一般在 10 到 20 个左右&#xff0c;光谱分辨率通常在几十纳米到几百纳米之间&#xff0c;如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…

RAG 切块Chunk技术总结与自定义分块实现思路

TrustRAG项目地址&#x1f31f;&#xff1a;https://github.com/gomate-community/TrustRAG 可配置的模块化RAG框架 切块简介 在RAG&#xff08;Retrieval-Augmented Generation&#xff09;任务中&#xff0c;Chunk切分是一个关键步骤&#xff0c;尤其是在处理结构复杂的PDF文…

Java基础——概念和常识(语言特点、JVM、JDK、JRE、AOT/JIT等介绍)

我是一个计算机专业研0的学生卡蒙Camel&#x1f42b;&#x1f42b;&#x1f42b;&#xff08;刚保研&#xff09; 记录每天学习过程&#xff08;主要学习Java、python、人工智能&#xff09;&#xff0c;总结知识点&#xff08;内容来自&#xff1a;自我总结网上借鉴&#xff0…

Low-Level 大一统:如何使用Diffusion Models完成视频超分、去雨、去雾、降噪等所有Low-Level 任务?

Diffusion Models专栏文章汇总&#xff1a;入门与实战 前言&#xff1a;视频在传输过程中常常因为各种因素&#xff08;如恶劣天气、噪声、压缩和传感器分辨率限制&#xff09;而出现质量下降&#xff0c;这会严重影响计算机视觉任务&#xff08;如目标检测和视频监控&#xff…

矩阵碰一碰发视频源码技术开发全解析,支持OEM

在当今数字化内容传播迅速发展的时代&#xff0c;矩阵碰一碰发视频功能以其便捷、高效的特点&#xff0c;为用户分享视频提供了全新的体验。本文将深入探讨矩阵碰一碰发视频源码的技术开发过程&#xff0c;从原理到实现&#xff0c;为开发者提供全面的技术指引。 一、技术原理 …

测试工程师的linux 命令学习(持续更新中)

1.ls """1.ls""" ls -l 除文件名称外&#xff0c;亦将文件型态、权限、拥有者、文件大小等资讯详细列出 ls -l等同于 ll第一列共10位&#xff0c;第1位表示文档类型&#xff0c;d表示目录&#xff0c;-表示普通文件&#xff0c;l表示链接文件。…

HJ34 图片整理(Java版)

一、试题地址 图片整理_牛客题霸_牛客网 二、试题描述 描述 对于给定的由大小写字母和数字组成的字符串&#xff0c;请按照 ASCIIASCII 码值将其从小到大排序。 如果您需要了解更多关于 ASCIIASCII 码的知识&#xff0c;请参考下表。 输入描述&#xff1a; 在一行上输入一…

web开发工具之:三、JWT的理论知识,java的支持,封装的工具类可以直接使用

文章目录 前言一、JWT的理论知识1. 什么是 JWT&#xff08;JSON Web Token&#xff09;&#xff1f;2. **JWT 的组成**3. **JWT 的特点**4. **JWT 的使用场景**5. **JWT 的生命周期**6. **JWT 的优点**7. **JWT 的注意事项**5. **JWT 示例**总结 二、java的springboot支持1. po…

电路笔记(信号):Python 滤波器设计分析工具pyfda

目录 滤波器设置(3步实现滤波器设计)数据分析与使用pyfda功能界面数字滤波器数学表示线性相位线性相位的定义线性相位的特性 冲击响应quartus数据加载 CG 滤波器设置(3步实现滤波器设计) pip install pyfda #安装python依赖&#xff0c;详见https://pyfda.readthedocs.io/en/la…

【15】Word:互联网发展状况❗

目录 题目​ NO2 NO3 NO4 NO5 NO6 NO7.8.9 NO7 NO8 NO9 NO10 题目 NO2 布局→页面设置→纸张&#xff1a;A4→页边距&#xff1a;上下左右→版式&#xff1a;页眉/页脚页码范围&#xff1a;多页&#xff1a;对称页边距→内侧/外侧→装订线 NO3 首先为文档应用内置…