面试: 单例模式

目录

一、饿汉单例(实现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 元素…

【保姆级讲解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…

学习笔记之——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

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;以及点击查看博客可以…

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

企业网络安全威胁概述 外部威胁&#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;

微信小程序自定义关闭按钮在弹窗下面的效果

效果图: 我之前用vant 的popup的弹窗写&#xff0c;会出现close图标移动到弹窗内容外部不可见。 自定义代码&#xff1a; popup.JS/*** 生命周期函数--监听页面初次渲染完成*/onReady() {//自定义弹窗 动态获取屏幕高度var that this;wx.getSystemInfo({success: (result) &…

探探各个微前端框架

本文作者为 360 奇舞团前端开发工程师 微前端架构是为了在解决单体应用在一个相对长的时间跨度下&#xff0c;由于参与的人员、团队的增多、变迁&#xff0c;从一个普通应用演变成一个巨石应用(Frontend Monolith)后&#xff0c;随之而来的应用不可维护的问题。这类问题在企业级…

【ELFK】Filebeat+ELK 部署

FilebeatELK 部署 Node1节点&#xff08;2C/4G&#xff09;&#xff1a;node1/192.168.67.11 Elasticsearch Kibana Node2节点&#xff08;2C/4G&#xff09;&#xff1a;node2/192.168.67.12 Elasticsearch Apache节点&#xff1a;apache/192.168.67.10 …

linux学习:队列

目录 顺序队列 管理结构体设计 初始化 入队 出队 链式队列 例子 用户输入整数则入队&#xff0c;字母则出队 我们对队列里的元素操作是有严格限制的&#xff1a;插入一个新节点&#xff0c;必须插入到 指定的一端&#xff0c;而删除一个已有节点&#xff0c;则必须在另…

掌握 C# 爬虫技术:使用 HttpClient 获取今日头条内容

摘要/导言&#xff1a; 在本文中&#xff0c;我们将探讨如何使用 C# 中的 HttpClient 类和爬虫代理IP技术来获取今日头条的内容。我们还将实现多线程技术&#xff0c;以提高数据采集的效率。 背景/引言&#xff1a; 随着信息时代的到来&#xff0c;数据已经成为了一种非常宝…

开发日志2024-04-11

开发日志2024/04/11 1、会员/普通用户预约完成后&#xff0c;技师对应的积分添加预约完成的项目价格添加到统计表的业绩字段中&#xff0c;同时对应的服务次数字段1 实现代码&#xff1a; 前端 shHandler(){this.$confirm(确定操作?, "提示", {confirmButtonText…

HarmonyOS实战开发-拼图、如何实现获取图片,以及图片裁剪分割的功能。

介绍 该示例通过ohos.multimedia.image和ohos.multimedia.mediaLibrary接口实现获取图片&#xff0c;以及图片裁剪分割的功能。 效果预览 使用说明&#xff1a; 使用预置相机拍照后启动应用&#xff0c;应用首页会读取设备内的图片文件并展示获取到的第一个图片&#xff0c;…