面试: 单例模式

目录

一、饿汉单例(实现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.mzph.cn/news/808908.shtml

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

相关文章

CSS导读 (元素显示模式)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 三、CSS的元素显示模式 3.1 什么是元素显示模式 3.2 块元素 3.3 行内元素 3.4 行内块元素 3.5 元素…

UNIAPP二维码展示页亮度调至最亮返回恢复进入前亮度

onLoad(params) {let num plus.screen.getBrightness().toString(); //转字符串是要存到stoage中number类型会存储失败plus.storage.setItem("pmld", num)plus.screen.setBrightness(1); //设置屏幕亮度&#xff0c;范围0-1 }onUnload() {let platformuni.getSystem…

创建自定义 通知栏

//创建前台服务方式/*** description* author* time*/ class MyForegroundService : Service() {companion object {private var instance: MyForegroundService? nullfun getInstance(): MyForegroundService? {return instance}}private val NOTIFICATION_ID 1private va…

【保姆级讲解Element UI】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

结合fastapi-users与Langserve轻松实现大语言接口用户认证

在做大模型开发的过程中&#xff0c;相信很多小伙伴都是对大模型开发感兴趣&#xff0c;却对 fastapi 这个框架并不熟悉&#xff0c;但是&#xff0c;实际开发的项目确需要用户鉴权&#xff0c;这时候就会很头疼&#xff0c;查阅官方文档发现&#xff0c;官方虽然有例子&#x…

uni-app的地图定位与距离测算功能的实现

文章目录 一、引言二、uni-app地图定位实现三、距离测算技术四、完整代码五、结论本文着重探讨了如何在uni-app中实现地图定位,以及如何计算当前定位与目标位置之间的距离。 一、引言 在移动应用开发中,地图定位与距离测算是常见的功能需求。无论是出行导航、位置签到,还是…

学习笔记之——3DGS-SLAM系列代码解读

最近对一系列基于3D Gaussian Splatting&#xff08;3DGS&#xff09;SLAM的工作的源码进行了测试与解读。为此写下本博客mark一下所有的源码解读以及对应的代码配置与测试记录~ 其中工作1~5的原理解读见博客&#xff1a; 学习笔记之——3D Gaussian Splatting及其在SLAM与自动…

ios包上架系列 二、Xcode打应用市场ipa包

打包的时候一定要断开网络&#xff0c;上线包名只能在打包机配置 检查是否是正式环境&#xff0c;先在模拟器上运行 1、版本名称和本号号记得在这里更改&#xff0c;否则不生效 原因 &#xff1a;info.list <string>$(FLUTTER_BUILD_NAME)</string><key>CFB…

mysql查看数据库表容量大小

【推荐】单表行数超过 500 万行或者单表容量超过 2GB&#xff0c;才推荐进行分库分表。 说明&#xff1a;如果预计三年后的数据量根本达不到这个级别&#xff0c;请不要在创建表时就分库分表。 1. 查询所有数据库记录数和容量 SELECTtable_schema AS 数据库,SUM(table_rows) …

贪心算法|763.划分字母区间

力扣题目链接 class Solution { public:vector<int> partitionLabels(string S) {int hash[27] {0}; // i为字符&#xff0c;hash[i]为字符出现的最后位置for (int i 0; i < S.size(); i) { // 统计每一个字符最后出现的位置hash[S[i] - a] i;}vector<int> …

jenkins 启动linux节点时 控制台中文显示问号乱码

新增一个jenkins节点时&#xff0c;遇到了控制台中文输出问号的问题。 网上各种配置jenkins的全局变量&#xff0c;都不行。 最终是 节点列表 ->对应节点 -> 启动方式 -> 高级 添加JVM选项 -Dfile.encodingUTF-8

图像处理-采样方法概述

在图像处理中&#xff0c;上采样&#xff08;upsampling&#xff09;和下采样&#xff08;downsampling&#xff09;是常用的操作&#xff0c;用于改变图像的分辨率或大小。这些方法通常用于图像处理任务&#xff0c;如图像放大、缩小、压缩等。下面是一些常见的上采样和下采样…

MySQL基础练习题:习题16-20

这部分主要是为了帮助大家回忆回忆MySQL的基本语法&#xff0c;数据库来自于MySQL的官方简化版&#xff0c;题目也是网上非常流行的35题。这些基础习题基本可以涵盖面试中需要现场写SQL的问题。 列出部门名称和这些部门的员工信息&#xff0c;同时列出没有员工的部门 唯一要注…

面试题:Rabbitmq怎么保证消息的可靠性?

面试题&#xff1a;Rabbitmq怎么保证消息的可靠性? RabbitMQ作为一款广泛使用的消息中间件&#xff0c;提供了多种机制来确保消息的可靠性。要保证消息的可靠性&#xff0c;需要在消息的生产和消费过程中考虑以下几个关键方面&#xff1a; 1. 消息持久化 生产者端持久化 发…

Python 序列化与反序列化

目录 1、基本概念 2、JSON模块 2.1、dumps() 与 loads() 函数 2.2、dump() 与 load() 函数 2.3、bool 、None 类型的序列化与反序列化 3、pickle模块 3.1、dumps() 与 loads() 函数 3.2、dump() 与 load() 函数 1、基本概念 说明&#xff1a;通过文件操作&#xff0c;…

个人博客系统项目(SpringBoot+Linux部署上线)

在学完SpringBoot框架、MyBatis后&#xff0c;直接开始做第一个项目&#xff1a;博客系统 首先&#xff0c;该博客系统包含核心功能有&#xff1a; 一、登录、注册、退出登录功能。 二、没有登陆前可以查看博客首页以及博客展示的分页处理&#xff0c;以及点击查看博客可以…

Restful API接口规范(以Django为例)

Restful API接口规范(以Django为例) Restful API的接口架构风格中制定了一些规范&#xff0c;极大的简化了前后端对接的时间&#xff0c;以及增加了开发效率 安全性保证–使用https路径中带 api标识路径中带版本号数据即资源&#xff0c;通常使用名词操作请求方式决定操作资源…

浅谈网络安全威胁与防御策略

企业网络安全威胁概述 外部威胁&#xff1a;来自网络安全威胁&#xff0c;比如DDOS攻击&#xff0c;病毒&#xff0c;sql注入&#xff0c;木马&#xff0c;蠕虫&#xff0c;等网络入侵&#xff0c;网络扫描&#xff0c;垃圾邮件&#xff0c;钓鱼邮件&#xff0c;针对web的攻击…

集合系列(十九) -List与数组互转操作介绍

一、数组转List 方式一 通过 Arrays.asList(strArray) 方式&#xff0c;将数组转换List&#xff0c;但不能对List增删&#xff0c;只能查改&#xff0c;否则抛异常&#xff0c;例子如下&#xff1a; public static void main(String[] args) {//创建一个字符串数组String[] …

小程序中配置scss

找到&#xff1a;project.config.json 文件 setting 模块下添加&#xff1a; "useCompilerPlugins": ["sass","其他的样式类型"] 配置完成后&#xff0c;重启开发工具&#xff0c;并新建文件 结果&#xff1a;