几种场景的单例模式思考总结(饿汉、懒汉、线程安全懒汉、反射破坏、反序列化破坏)

本文主要是介绍几种场景的单例模式思考总结(饿汉、懒汉、线程安全懒汉、反射破坏、反序列化破坏),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天先直接上代码,后续在补充一下单例模式的定义。。

饿汉式单例模式(线程安全):

public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}

懒汉式单例模式(非线程安全):

public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

懒汉式单例模式(线程安全,双重检查锁定):

public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

反射破坏单例(非线程安全):

其中反射破坏单例是指通过反射机制,可以绕过单例模式的控制,从而在单例类的构造方法中多次创建实例,破坏了单例模式的设计意图。

所以通过在单例类的构造方法中增加判断,如果已经存在实例,则抛出异常或返回已存在的实例。

public class Singleton {private static Singleton instance;private Singleton() {if (instance != null) {throw new RuntimeException("Cannot instantiate singleton class using reflection");}}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

反序列化破坏单例(线程安全):

反序列化破坏单例是指在使用序列化和反序列化机制时,可能会破坏单例模式的设计。Java 的序列化机制允许将对象转换为字节序列,以便于存储或传输,而反序列化则是将字节序列还原为对象。
**在单例类中增加 readResolve() 方法是为了在对象反序列化时返回同一实例,从而保证单例的唯一性。**这样可以防止在反序列化时创建多个实例,保持了单例模式的设计意图。
在给定的代码中,readResolve() 方法返回的是单例类的静态实例 instance,这意味着无论在何种情况下反序列化该对象,都将返回同一个实例。这样可以确保反序列化的对象与已存在的单例实例相同,避免了创建新的实例,从而保持了单例的唯一性。
需要注意的是,readResolve() 方法的访问控制符应该是 private,以确保只有单例类本身可以调用该方法,防止在外部通过反射等方式调用。

import java.io.Serializable;public class Singleton implements Serializable {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}// 在反序列化过程中,readResolve() 方法会在对象反序列化时被调用,直接返回单例实例,确保单例的唯一性。protected Object readResolve() {return instance;}
}

这篇关于几种场景的单例模式思考总结(饿汉、懒汉、线程安全懒汉、反射破坏、反序列化破坏)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

Nginx location匹配模式与规则详解

《Nginxlocation匹配模式与规则详解》:本文主要介绍Nginxlocation匹配模式与规则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、环境二、匹配模式1. 精准模式2. 前缀模式(不继续匹配正则)3. 前缀模式(继续匹配正则)4. 正则模式(大

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F