面试: 单例模式

目录

一、饿汉单例(实现Serializable)

1、破坏单例的三种情况

(1)反射破坏单例

(2)反序列化破坏单例

(3)Unsafe破坏单例

2、饿汉单例(利用枚举实现)

二、懒汉单例(DCL实现)

1、多线程时会发生的错误

2、懒汉单例(内部类实现)

三、在哪些地方用到了单例模式


一、饿汉单例(实现Serializable)

在类执行初始化操作时,单例就会被创建,JVM会保证线程安全

public class Singleton implements Serializable{private Singleton() {System.out.println("111");}private static final Singleton INS = new Singleton();//先创建好对象public static Singleton getInstance() {//在需要使用时直接调用return INS;}}

1、破坏单例的三种情况

(1)反射破坏单例
reflection(Singleton.class);

反射后创建了两个对象,使得单例被破坏。要想预防,在单例接口中加上以下代码

	private Singleton() {if(INS!=null) {throw new RuntimeException("单例不可被创建");}System.out.println("111");}

直接抛出异常。

(2)反序列化破坏单例
serializable(Singleton.getInstance());
  • 将单例对象转换为字节流,又将字节流读取为对象,就实现了单例破坏;
  • 因为重新被读取的对象并不是原来的对象,而是新建的一个对象。
	private static void serializable(Object instance) throws IOException,ClassNotFoundException {ByteArrayOutputStream bos = new ByteArrayOutputStream();Objectoutputstream oos = new Objectoutputstream(bos);oos.writeObject(instance);ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));system.out.println("反序列化创建实例:" + ois.readObject());}

想要预防,在单例代码中实现这个方法

public Object readResolve(){return INS;
}

这样就会利用这个方法的返回值作为结果返回,就不会用字节数组反序列化生成的对象了,这样就保证了对象的单例。

(3)Unsafe破坏单例
unsafe(Singleton.class);

利用实例的类型来创建一个实例,不会走构造方法来创建。

private static void unsafe(Class<?> clazz) throws InstantiationException {Object o = Unsafeutils.getUnsafe().allocateInstance(clazz);system.out.println( "Unsafe 创建实例:" + o);
}

2、饿汉单例(利用枚举实现)

public enum Singleton{INS;
}
  • 这种方法实现可以避免被,反射和反序列化破坏单例;
  • 在反射时,java会做相应的检查,以阻止调用枚举类的构造。
  • 在反序列化时,java会直接返回枚举类实现的对象。
  • 挡不住unsafe。

二、懒汉单例(DCL实现)

public class singleton implements serializable {private singleton() { system.out.println("private Singleton()");}private static volatile singleton INSTANCE = null;public static singleton getInstance() {if (INSTANCE == null) {synchronized (singleton.class) {if (INSTANCE == null) {INSTANCE = new singleton();}}}return INSTANCE;
}
  • 双端检索可以避免对象被重复创建;
  • 如果没有第二次检查null,就可能发生,一个等待锁的线程,进入创建对象的程序;
  • 添加volatile关键字可以避免指令重排序,因为在JVM中,构建对象的指令有一定的因果关系,如果不使用volatile方法的话,就会产生构建失败的情况。

1、多线程时会发生的错误

  • 在JVM执行INSTANCE=对象后,另一个线程直接返回了INSTANCE对象,但是这个对象的成员变量是没有被完全赋值的;
  • 在加上volatile后,指令后会加上一个内存屏障,这样就阻止了内存重新排序。

2、懒汉单例(内部类实现)

既能保证线程安全,又可以消灭懒汉在第一次使用时才创建对象的特性。

三、在哪些地方用到了单例模式

  • Runtime类
  • System类
  • Collection类
  • Comparator接口
  • Comparators类

 

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

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

相关文章

通过调用Vcenter-Api获取Vcenter中服务器信息

通过调用Vcenter-Api获取Vcenter中服务器信息 文章目录 通过调用Vcenter-Api获取Vcenter中服务器信息1. 获取Vmware API帮助文档2. 获取访问凭证3. 获取服务器清单4. 获取服务器更多信息5. 获取虚机更多信息6. 获取磁盘信息7. 获取操作系统相关 1. 获取Vmware API帮助文档 htt…

VUE typescript 调用stompjs[Rabbit MQ]

npm拉下来最新的2.3.9版本&#xff0c;发现一些原来Js代码已经不能用了。顺便解读了下最新定义的内容 // <reference types"node" />export const VERSIONS: {V1_0: string;V1_1: string;V1_2: string;supportedVersions: () > string[]; };export class C…

面试经典算法系列之二叉树5 -- 二叉树的前序遍历

面试经典算法20 - 二叉树的前序遍历 LeetCode.144 公众号&#xff1a;阿Q技术站 问题描述 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#xff1a; 输入&…

结合ArcGIS+SWAT模型+Century模型:流域生态系统水-碳-氮耦合过程模拟

原文链接&#xff1a;结合ArcGISSWAT模型Century模型&#xff1a;流域生态系统水-碳-氮耦合过程模拟https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&tempkeyMTI2NV9sMGRZNUJoVkNVc1ZzSzRuMl9XXzhqX0R3cXpESWFwM1E4cFY4ejNqWFh3VUl0dlZkNWk4b20ydFdFTy1xS2ZObGN0Z0ZXSjly…

怎么在外地控制自家的电视

怎么在外地控制自家的电视 随着科技的进步和智能家居的普及&#xff0c;远程控制家中的电器设备已经成为现实。电视作为家庭娱乐的中心&#xff0c;远程控制功能更是备受关注。那么&#xff0c;如何在外地控制自家的电视呢&#xff1f;本文将为你提供详细的步骤和有价值的信息…

医院订餐平台:为患者提供贴心服务的创新解决方案

在现代医疗服务中&#xff0c;患者的就餐问题一直是一个备受关注的议题。传统的医院饮食服务往往面临着餐品单一、服务不及时等问题&#xff0c;无法满足患者的个性化需求。为了提高患者的就餐体验&#xff0c;医院订餐平台应运而生&#xff0c;通过数字化、个性化的服务&#…

【域适应】基于深度域适应MMD损失的典型四分类任务实现

关于 MMD &#xff08;maximum mean discrepancy&#xff09;是用来衡量两组数据分布之间相似度的度量。一般地&#xff0c;如果两组数据分布相似&#xff0c;那么MMD 损失就相对较小&#xff0c;说明两组数据/特征处于相似的特征空间中。基于这个想法&#xff0c;对于源域和目…

【HTML】制作一个简单的线性动画

目录 前言 HTML部分 CSS部分 JS部分 效果图 总结 前言 无需多言&#xff0c;本文将详细介绍一段HTML代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建一个文本文档&#xff0c;两个文件夹&#xff0c;其中HTML的文件名改为[index.html]&am…

前端对接fastGPT流式数据+打字机效果

首先在对接api时 参数要设置stream: true, const data {chatId: abc,stream: true,//这里true返回流式数据detail: false,variables: {uid: sfdsdf,name: zhaoyunyao,},messages: [{ content: text, role: user }]}; 不要用axios发请求 不然处理不了流式数据 我这里使用fetch …

赋能技术 助锂制造|青软青之助力锂电检测行业数字化升级

在全球范围内&#xff0c;新能源转型已成为时代的必然选择。随着“双碳”目标的深入推进&#xff0c;这一趋势愈发明显。而作为新能源领域的一颗璀璨明珠&#xff0c;锂电池的研发、产业链建设和技术创新&#xff0c;无疑是这场能源革命的核心所在。其产业链的日趋完善、技术的…

通过WebShell登录SQL Server主机并使用SSRS报表服务

背景信息 RDS SQL Server提供了WebShell功能&#xff0c;允许用户通过Web界面登录到RDS SQL Server实例的操作系统中&#xff0c;并在该操作系统中执行命令、上传下载文件等操作。WebShell功能方便用户对RDS SQL Server实例的管理和维护&#xff0c;特别是在无法使用SSH客户端的…

PyTorch-Lightning:trining_step的自动优化

文章目录 PyTorch-Lightning&#xff1a;trining_step的自动优化总结&#xff1a; class _ AutomaticOptimization()def rundef _make_closuredef _training_stepclass ClosureResult():def from_training_step_output class Closure PyTorch-Lightning&#xff1a;trining_ste…