深度解析单例模式

news/2024/4/29 14:14:29/文章来源:https://blog.csdn.net/weixin_44817884/article/details/136988942

一、概述

1.1 特点

  1. 单例类。只有一个实例对象
  2. 该单例对象必须由单例类自行创建
  3. 单例类对外提供一个访问该单例的全局访问点

1.2 优缺点

优点:

  1. 保证内存里只有一个实例,减少了内存的开销
  2. 可以避免对资源的多重占用

缺点:

  1. 没有接口,扩展困难。违背开闭原则
  2. 不利于代码调试。调试过程中,如果单例代码没有执行完,不能创建一个对象

1.3 应用场景

  1. 频繁创建类,使用单例可以降低系统的内存压力,减少GC。
  2. 全局信息类。利用一个类记录网站的访问次数,不希望有的访问被记录在对象A上,有的记录在对象B上。

二、八种经典实现方式

2.1 饿汉式

代码实现:

public class Hungry {private Hungry(){};// 1. 静态变量 // private static Hungry hungry = new Hungry(); // 2. 静态代码块 private final static Hungry hungry; static { hungry = new Hungry(); } public static Hungry getInstance() { return hungry; } 
}

优点: 类加载时,就把实例初始化。
缺点: 浪费内存空间。

2.2 懒汉式

代码实现:

// 1. 线程不安全
// 2. 线程安全,synchronized修饰方法
// 3. 线程安全,synchronized代码块修饰
public class Lazy {private Lazy(){}// 1. 多线程不安全private static Lazy lazy = null;public Lazy getInstance() {if (lazy == null) {lazy = new Lazy();}return lazy;}// 2. 线程安全,synchronized修饰方法。多线程无法并行处理,效率低下public synchronized Lazy getInstance() {if (lazy == null) {lazy = new Lazy();}return lazy;}// 3. 线程安全,synchronized代码块修饰. 产生多个实例,即多个线程都通过lazy==null的判断public static Lazy getInstance(){if (lazy == null) {synchronized (Lazy.class){lazy = new Lazy();}}return lazy;}    

适用场景: 如果程序一开始要加载的资源太多,可以使用懒加载。

2.3 双重检查方式

代码实现:

// 1. 双重检测1:线程安全,效率较高,延迟加载;
// 但存在指令重排,即创建对象需要3个步骤,3个步骤之间可能会重排,导致空指针
// 异常
// 2. 双重检测2:利用volatile修饰的变量;volatile可以防止指令重排
public class DoubleCheck {private DoubleCheck(){}// 1. 双重检测1 // private static DoubleCheck doubleCheck;// 2. 双重检测2private volatile static DoubleCheck doubleCheck;public static DoubleCheck getInstance() {if (doubleCheck == null) {synchronized (DoubleCheck.class) {if (doubleCheck == null) {doubleCheck = new DoubleCheck();}}}return doubleCheck;}
}
优点:线程安全;延迟加载;效率较高

2.4 静态内部类方式

public class Inner {private Inner(){}public static Inner getInstance() {return InnerClass.inner;}private static class InnerClass{private static final Inner inner = new Inner();}
}
静态内部类方式在Inner类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载
InnerClass类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化
时,别的线程是无法进入的。
【优点】:避免了线程不安全,延迟加载,效率高

2.5 枚举类方式

// 最安全
public enum EnumSingle {INSTANCE;public static EnumSingle getInstance(){return INSTANCE;}
}
优点:
1. 写法简单
2. 线程安全
3. 避免反序列化破坏单例

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

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

相关文章

如何使用 ArcGIS Pro 制作三维建筑

三维地图已经逐渐成为未来地图的趋势,对于大范围应用,只需要普通的建筑体块就行,如果有高程数据,还可以结合地形进行显示,这里为大家介绍一下 ArcGIS Pro 制作三维建筑的方法,希望能对你有所帮助。 数据来…

使用seldom编写http接口用例

在编写接口用例的过程中,针对一个接口,往往只是参数不同,那么参数化就非常有必要了。 seldom 中参数化的用法非常灵活,这里仅介绍file_data() 的N种玩法。 二维列表 当参数比较简单时可以试试下面的方式。 参数化数据 {"…

老阳推荐的视频号项目是真的吗?能赚钱吗?

在当下数字化、信息化的社会背景下,视频号项目如雨后春笋般涌现,成为许多人关注的焦点。特别是在一些知名人士,如老阳的推荐下,这些项目更是受到了广泛的关注和讨论。那么,老阳推荐的视频号项目是否真实存在?它能否真…

uni-app(使用阿里图标)

1.注册阿里矢量图标库 注册阿里图标库账号并登录,https://www.iconfont.cn/ 2.加入购物车 搜索适合自己的图标,加入购物车,如下图: 3.加入项目 我的->资源管理->我的项目->创建项目,然后返回购物车&#…

cesium vue 绘制标记实体(撒点),监听鼠标左击事件

添加实体 const viewer new Cesium.Viewer(cesiumContainer, {})viewer.entities.add()查看实体 const viewer new Cesium.Viewer(cesiumContainer, {}) const billboard viewer.entities.add({...})viewer.zoomTo(billboard)删除实体 根据实体删除 if (billboard.value…

快速上手Spring Cloud 六:容器化与微服务化

快速上手Spring Cloud 一:Spring Cloud 简介 快速上手Spring Cloud 二:核心组件解析 快速上手Spring Cloud 三:API网关深入探索与实战应用 快速上手Spring Cloud 四:微服务治理与安全 快速上手Spring Cloud 五:Spring …

目标检测+车道线识别+追踪

一种方法: 车道线检测-canny边缘检测-霍夫变换 一、什么是霍夫变换 霍夫变换(Hough Transform)是一种在图像处理和计算机视觉中广泛使用的特征检测技术,主要用于识别图像中的几何形状,尤其是直线、圆和椭圆等常见形状…

C++从入门到精通——函数重载

函数重载 前言一、函数重载概念二、函数重载的分类参数类型不同的函数重载参数个数不同的函数重载参数类型顺序不同的函数重载 三、函数重载的具体代码展示main.cpp 四、为什么为什么C支持函数重载,而C语言不支持函数重载呢 前言 函数重载是指在同一个作用域内&…

argo rollout使用

一、前言 argorollout是比argocd更高级的发布工具,其中包含自动化金丝雀发布、自动化蓝绿发布、还可以通过argo命令或者dashboard查看发布的过程 二、使用 需要先部署argo rollout服务 参考:https://github.com/argoproj/argo-rollouts/tree/master/m…

微信小程序的页面制作---常用组件及其属性2

一、标签栏taBar 在全局配置文件app.json中添加taBar配置,可实现标签栏配置。标签栏最少2个,最多5个 (1)如何配置标签栏? 1》先建多个文件,(以我的index,list,myform文…

RelayAttention:让大型语言模型更高效地处理长提示符

一、前言 虽然大型语言模型 (LLM) 近年来取得了非常显著的进展,也在各种自然语言处理任务中展现出强大的能力。然而,LLM 的在实际的应用落地层面也面临着一些实际挑战,其中之一就是效率和成本问题,导致了在垂直行业实际落地的应用…

CE-Net:用于2D医学图像分割的上下文编码器网络

CE-Net:用于2D医学图像分割的上下文编码器网络 摘要引言方法 【2019】CE-NetContext Encoder Network for 2D Medical Image Segmentation 摘要 医学图像分割是医学图像分析中的重要步骤。随着卷积神经网络在图像处理中的快速发展,深度学习已经被用于医…

服务器被攻击有什么表现?

引言 在现今高度互联的网络环境中,服务器安全已成为每个企业和个人站长不容忽视的重要议题。服务器作为承载关键业务和数据的核心设施,一旦遭受攻击,不仅可能导致服务中断、数据泄露,还可能带来严重的经济损失和声誉损害。本文旨…

【二叉树】Leetcode 98. 验证二叉搜索树【中等】

验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例1&a…

fpga 通过axi master读写PS侧DDR的仿真和上板测试

FPGA和ARM数据交互是ZYNQ系统中非常重要的内容。PS提供了供FPGA读写的AXI-HP接口用于两者的高速通信和数据交互。一般的,我们会采用AXI DMA的方式去传输数据,DMA代码基本是是C编写,对于FPGA开发者来说不利于维护和debug。本文提供一种手写AXI…

6、鸿蒙学习-Stage模型应用程序包结构

基于Stage模型开发的应用,经编译打包后,其应用程序的结构如下图应用程序包结构(Stage模型)所示。开发者需要熟悉应用程序包结构相关的基本概念。 一、在开发态,一个应用包含一个或者多个Module,可以在DevE…

“免密支付”出事了?看看背后的安全隐患

#免密支付# 的安全问题近日冲上热搜,大家来看看怎么一回事。 “我不知道什么时候开通的‘免密支付’功能,直到手机频繁收到账单提醒,才发现平台账号被盗,对方通过‘免密支付’消费了5000多元。这种事关会员安全的操作提示应该设置…

机器学习概论—增强学习

机器学习概论—增强学习 强化学习(Reinforcement Learning, RL)或者说是增强学习,是机器学习的一个领域,旨在使智能体通过与环境的交互学习如何做出决策,它是关于在特定情况下采取适当的行动来最大化奖励。它被各种软件和机器用来寻找在特定情况下应采取的最佳行为或路径…

无忧微服务:如何实现大流量下新版本的发布自由

作者:项良、十眠 微服务上云门槛降低,用好微服务才是关键 据调研数据显示,约 70% 的生产故障是由变更引起的。在阿里云上的企业应用如茶百道、极氪汽车和来电等,他们是如何解决变更引起的稳定性风险,实现了在白天高流…

etf期权开户有哪些基本条件,期权的佣金最低多少?

在中国开设etf期权账户,投资者需要满足一系列的基本条件。首先,投资者的证券账户日均客户权益不得低于50万元人民币,且需有6个月以上的证券或期货交易经验。此外,投资者还必须通过相关的测试,并具备被认可的期权模拟交…