单例模式实现案例

单例模式实现案例

文章目录

  • 单例模式实现案例
    • **饿汉式**
    • **枚举饿汉式**
    • **懒汉式**
    • **双检锁懒汉式**
    • **内部类懒汉式**

单例模式概念: 单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。这对于需要在系统中共享某个资源(例如配置信息、数据库连接池等)的场景非常有用。

饿汉式(Eager Initialization): 在类加载时就创建实例,线程安全,但可能会造成资源浪费。你已经提供了一个经典的饿汉式实现。

懒汉式(Lazy Initialization): 在需要时才创建实例,可能存在线程安全问题,需要进行同步处理。你已经给出了懒汉式和双检锁懒汉式的实现,其中双检锁懒汉式通过双重检查锁定和volatile关键字确保了线程安全。

枚举单例模式: 利用枚举类型的特性,天然防止反射和反序列化攻击。你已经提供了一个枚举饿汉式的实现。

静态内部类单例模式: 使用静态内部类的方式来延迟加载实例,避免了同步问题,也能够天然防止反射和反序列化攻击。你已经给出了一个内部类懒汉式的实现。

为什么 DCL(Double-Checked Locking)中要使用 volatile: 在双检锁懒汉式中,volatile关键字确保了可见性和防止指令重排序。如果没有volatile,在多线程环境中,一个线程可能会看到一个未完全构造的实例,导致不正确的结果。

防止反射攻击: 在饿汉式和懒汉式中,通过在构造方法中加入特定逻辑,可以防止反射攻击。在枚举和静态内部类实现中,由于它们的特性,天然不容易受到反射攻击。

防止反序列化攻击: 在饿汉式和懒汉式中,通过实现readResolve方法可以防止反序列化攻击。在枚举实现中,由于枚举类型的特性,不容易受到反序列化攻击。
要求

  • 掌握五种单例模式的实现方式
  • 理解为何 DCL 实现时要使用 volatile 修饰静态变量
  • 了解 jdk 中用到单例的场景

饿汉式

public class Singleton1 implements Serializable {private Singleton1() {if (INSTANCE != null) {throw new RuntimeException("单例对象不能重复创建");}System.out.println("private Singleton1()");}private static final Singleton1 INSTANCE = new Singleton1();public static Singleton1 getInstance() {return INSTANCE;}public static void otherMethod() {System.out.println("otherMethod()");}public Object readResolve() {return INSTANCE;}
}
  • 构造方法抛出异常是防止反射破坏单例
  • readResolve() 是防止反序列化破坏单例

枚举饿汉式

public enum Singleton2 {INSTANCE;private Singleton2() {System.out.println("private Singleton2()");}@Overridepublic String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}public static Singleton2 getInstance() {return INSTANCE;}public static void otherMethod() {System.out.println("otherMethod()");}
}
  • 枚举饿汉式能天然防止反射、反序列化破坏单例

懒汉式

public class Singleton3 implements Serializable {private Singleton3() {System.out.println("private Singleton3()");}private static Singleton3 INSTANCE = null;// Singleton3.classpublic static synchronized Singleton3 getInstance() {if (INSTANCE == null) {INSTANCE = new Singleton3();}return INSTANCE;}public static void otherMethod() {System.out.println("otherMethod()");}}
  • 其实只有首次创建单例对象时才需要同步,但该代码实际上每次调用都会同步
  • 因此有了下面的双检锁改进

双检锁懒汉式

public class Singleton4 implements Serializable {private Singleton4() {System.out.println("private Singleton4()");}private static volatile Singleton4 INSTANCE = null; // 可见性,有序性public static Singleton4 getInstance() {if (INSTANCE == null) {synchronized (Singleton4.class) {if (INSTANCE == null) {INSTANCE = new Singleton4();}}}return INSTANCE;}public static void otherMethod() {System.out.println("otherMethod()");}
}

为何必须加 volatile:

  • INSTANCE = new Singleton4() 不是原子的,分成 3 步:创建对象、调用构造、给静态变量赋值,其中后两步可能被指令重排序优化,变成先赋值、再调用构造
  • 如果线程1 先执行了赋值,线程2 执行到第一个 INSTANCE == null 时发现 INSTANCE 已经不为 null,此时就会返回一个未完全构造的对象

内部类懒汉式

public class Singleton5 implements Serializable {private Singleton5() {System.out.println("private Singleton5()");}private static class Holder {static Singleton5 INSTANCE = new Singleton5();}public static Singleton5 getInstance() {return Holder.INSTANCE;}public static void otherMethod() {System.out.println("otherMethod()");}
}
  • 避免了双检锁的缺点

JDK 中单例的体现

  • Runtime 体现了饿汉式单例
  • Console 体现了双检锁懒汉式单例
  • Collections 中的 EmptyNavigableSet 内部类懒汉式单例
  • ReverseComparator.REVERSE_ORDER 内部类懒汉式单例
  • Comparators.NaturalOrderComparator.INSTANCE 枚举饿汉式单例

大家好,我是xwhking,一名技术爱好者,目前正在全力学习 Java,前端也会一点,如果你有任何疑问请你评论,或者可以加我QQ(2837468248)说明来意!希望能够与你共同进步

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

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

相关文章

Textract python 很好用的库

如何在Python中使用Textract的文章: 在Python中使用Textract Textract是一个强大的文本提取工具,它可以从各种类型的文件中提取文本,包括PDF,Word文档,PowerPoint演示文稿,JPEG图像等。以下是如何在Python…

如何配置一台高性能的IBM服务器

在当今信息化时代,服务器作为企业数据存储、处理和传输的核心设备,其性能的优劣直接关系到企业的运营效率和安全性。而IBM作为全球领先的企业级服务器提供商,其产品广泛应用于各行各业。本文将为你详细介绍如何配置一台高性能的IBM服务器&…

Linux Debian12使用VSCode和Python搭建flask开发环境

一、安装VSCode 在Linux Debian12系统上安装VSCode教程可以参考网上相关教程。 二、安装Python 打开VSCode,安装python和python扩展包,如下图所示: 三、创建Python虚拟环境 1.新建文件夹testFlask 2.用vscode打开文件夹testFlask&#xf…

QT中线程的退出分析

QT中线程的退出分析 前言开发环境代码的整改第一次修改第一次修改引起的问题问题原因分析解决方法第二次修改前言 软件实际开发过程中有好几处要实现这么一个功能:PC端软件“应用程序重启” ,本来这是一段比较简单的事情,但是因为重启软件报通信异常(错误日志中有记录通信…

前端 TS 语法继承 多态 修饰符 readonly 抽象类 ts 基本写法 可选 剩余参数 函数重载 接口 类(3)

继承 继承之间的叫法 A类继承了B类,那么A类叫做子类,B类叫成基类 子类 ---》派生类 基类 ---》超类(父类) // 继承之间的叫法 // A类继承了B类,那么A类叫做子类,B类叫成基类 // 子类 ---》派生类 // 基类 …

阅读笔记lv.1

阅读笔记 sql中各种 count结论不同存储引擎计算方式区别count() 类型 责任链模式常见场景例子(闯关游戏) sql中各种 count 结论 innodb count(*) ≈ count(1) > count(主键id) > count(普通索引列) > count(未加索引列)myisam 有专门字段记录…

Open3D 计算点云空间分布密度(16)

Open3D 计算点云空间分布密度(16) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 使用八叉树来估计点云密度可以通过统计每个体素内部的点的数量来实现。Open3D库中的VoxelGrid数据结构可以帮助完成这一任务。 二、算法实现 1.代码 代码如下(示例): import open3…

langchain-Agent-Agent类型和自定义Agent(代码)

本篇主要用于记忆Agent相关代码,不对各个类型Agent的功能和原理进行描述。 文章目录 代理类型reactplan&executestructured-chat 自定义代理 代理类型 react from langchain.agents import load_tools from langchain.agents import initialize_agent from l…

计算机体系结构----缓存一致性/多处理机

本文严禁转载,仅供学习使用。参考资料来自中国科学院大学计算机体系结构课程PPT以及《Digital Design and Computer Architecture》、《超标量处理器设计》、同济大学张晨曦教授资料。如有侵权,联系本人修改。 本文衔接上文计算机体系结构----存储系统 …

python爬虫,验证码识别,携带cookies请求

古诗词网案例!!! 识别验证码类型: # 此处用到的图片验证码识别网址为:http://ttshitu.com/ 图鉴 import base64 import json import requests # 一、图片文字类型(默认 3 数英混合): # 1 : 纯数字 # 1001:纯数字2 # 2 : 纯英文 # 1002:纯英文2 # 3 : 数英混合 # 1003:…

用通俗易懂的方式讲解:大模型微调方法总结

大家好,今天给大家分享大模型微调方法:LoRA,Adapter,Prefix-tuning,P-tuning,Prompt-tuning。 文末有大模型一系列文章及技术交流方式,传统美德不要忘了,喜欢本文记得收藏、关注、点赞。 文章目录 1、LoRA…

轻松查看WiFi密码的神奇脚本,让你忘记密码也不再是问题

说在前面 🎈本文介绍了一个便捷的脚本,可以帮助你获取电脑中保存的所有Wi-Fi网络的密码。不再需要担心忘记Wi-Fi密码或手动查找密码的麻烦,只需运行脚本即可一键获取。 一、引言 互联网的普及让我们离不开Wi-Fi网络,但忘记密码时…

怎么安装es、kibana(单点安装)

1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络: docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像,这个镜像体积非常大&#xff0c…

用C语言采集亚马逊amazon产品数据

上一篇文章我是用C写的一个爬取亚马逊的爬虫程序,相信大家已经看过了,这次呢,我依然使用C语言来写一个爬虫,大体上思路是和之前一样,只是支持的库以及语法有些区别,具体的呢我会一一解释出来,方…

android自定义来电秀UI

简单来电秀功能,效果如图: 底部附上demo 一、新建一个PhoneCallService服务,在服务中监听来电等状态,且控制UI显示 public class PhoneCallService extends InCallService {private final Call.Callback callback new Call.Ca…

仿真机器人-深度学习CV和激光雷达感知(项目2)day01

文章目录 前言项目介绍功能与技术简介硬件要求环境配置虚拟机运行项目demo 前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫本文内容是我为复试准备的第二个项目 💫欢迎大家的关注,我的博客主要关注…

如何给AI下达精准的指令,哪些提示词对于AI是有效的?

刚上手那会,我倾向于将 prompt 翻译为“指令”,但这并不精确。“指令”通常对应instructions,属于 prompt 中的纯指令部分,通常是一个动宾结构(做什么)。剩下的部分更多是描述(describe&#xf…

Open3D 不规则点云体积计算 (15)

Open3D 不规则点云体积计算 (15) 一、算法介绍二、算法实现1.代码2.结果黑暗笼罩万物,我将是黑暗中最后的那道曙光,以雷霆,击碎黑暗!!! 一、算法介绍 点云往往是不规则的,利用别的包围盒方法获取的体积可能不太准确,如果希望获取更准确的体积,这里介绍一种基于体素…

stable-diffusion 学习笔记

从效果看Stable Diffusion中的采样方法 参考:Ai 绘图日常 篇二:从效果看Stable Diffusion中的采样方法_软件应用_什么值得买 大概示例:

arm64架构编译electron长征路

文章目录 1. gn工具生成1.1 问题,找不到last_commit_position.h文件问题描述如下:解决方法1.2 ninja文件不是对应架构问题问题描述:解决方法1.3 问题3:clang++找不到问题描述解决方法2. electron 编译参数生成2.1 下载对应版本debian_bullseye_arm64-sysroot错误描述