大话设计模式——9.单例模式(Singleton Pattern)

简介

确保一个类只有一个实例,并提供全局访问点来获取该实例,是最简单的设计模式。

UML图:
在这里插入图片描述
单例模式共有两种创建方式:

  • 饿汉式(线程安全)

提前创建实例,好处在于该实例全局唯一,不存在线程冲突;坏处在于未使用时也会占用内存资源。

  • 懒汉式(原生写法存在线程冲突问题)

将实例的创建延迟到第一次使用时进行,相当于懒加载

创建步骤:

  • 私有化构造器
  • 提供唯一的全局访问接口
一、饿汉式
  1. 饿汉对象:
public class HungrySingleton {// 创建实例,类加载时已经确定实例,不存在线程冲突private static final HungrySingleton newInstance = new HungrySingleton();// 私有化构造器private HungrySingleton() {}public void processOn() {System.out.println("饿汉单例模式");}/*** 提供对外唯一访问实例的方法** @return*/public static HungrySingleton getInstance() {return newInstance;}
}
  1. 运行
public class Main {public static void main(String[] args) {HungrySingleton.getInstance().processOn();HungrySingleton hungrySingleton01 = HungrySingleton.getInstance();HungrySingleton hungrySingleton02 = HungrySingleton.getInstance();System.out.println(hungrySingleton02 == hungrySingleton01);}
}

在这里插入图片描述

二、懒汉式
  1. 原生写法
public class LazySingleton {// 实例对象private static LazySingleton instance = null;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}

存在线程安全隐患,多个线程进入可能会重复创建实例
在这里插入图片描述
在这里插入图片描述

改造

  • 方式1:同步方法
public class LazySingleton {// 实例对象private static LazySingleton instance = null;private LazySingleton() {}/*** 同步锁,每次只能允许一个线程进行获取* @return*/public static synchronized LazySingleton getInstanceSafely(){if (instance == null) {instance = new LazySingleton();}return instance;}
}

ps:改方式虽然可以确保线程安全,但是由于锁的粒度较大,高并发情况下系统性能会降低。

  • 方式2:同步代码块,使用volatile禁止指令重排,确保赋值时的原子操作同时使用DCL双重检查锁定 (Double-Checked-Locking),在多线程情况下保持高性能
public class LazySingleton {// 实例对象,禁止指令重排,确保原子操作private static volatile LazySingleton instance = null;private LazySingleton() {}/*** 同步锁,每次只能允许一个线程进行获取** @return*/public static LazySingleton getInstanceSafely02() {if (null == instance) {synchronized (LazySingleton.class) {// DCL双重检查锁定 if (null == instance) {instance = new LazySingleton();}}}return instance;}
}
总结

对象不复杂时,建议使用饿汉式。其他情况下使用懒汉式性能较好。

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

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

相关文章

C程序的编译

经过预处理后的源文件,退去一切包装,注释被删除,各种预处理命令也基本上被处理掉,剩下的就是原汁原味的C代码了。接下来的第二步,就开始进入编译阶段。编译阶段主要分两步:第一步,编译器调用一系列解析工具,去分析这些C代码,将C源文件编译为汇编文件;第二步,通过汇编…

anaconda创建了虚拟python环境,且安装了pytorch,但是pycharm中import torch运行时报错

报错如下: C:\Users\tashi\.conda\envs\test1\python.exe D:\project\python\transformer\main.py C:\Users\tashi\.conda\envs\test1\lib\site-packages\numpy\__init__.py:127: UserWarning: mkl-service package failed to import, therefore Intel(R) MKL init…

电子邮件协议学习

电子邮件协议学习 电子邮件服务器的核心功能是发送、接收和存储电子邮件;依赖于一系列协议,SMTP,IAMP,POP3,SMTPS ,IAMPS等协议。 SMTP(Simple Mail Transfer Protocol) 原理 SMTP基于文本的…

AI预测体彩排3第2弹【2024年4月13日预测--第1套算法开始计算第2次测试】

各位小伙伴,今天实在抱歉,周末回了趟老家,回来比较晚了,数据今天上午跑完后就回老家了,晚上8点多才回来,赶紧把预测结果发出来吧,虽然有点晚了,但是咱们前面说过了,目前的…

将Visio绘图导出PDF文件,使其自适应大小,并去掉导入Latex的边框显示

问题描述 将Visio绘图导成pdf文件,首先在Visio绘图如下: 如果直接导出或者另存为pdf文件,则会发现pdf文件是整个页面大小,而不是图片大小。而且在导入latex等排版工具现实时,会显示边框。 问题解决 1.调整Visio中的页…

mongodb中的多表查询aggregate中排序不是按全表排序,而是当前页排序问题如何解决?

在上篇文章中讲到了多表查询https://blog.csdn.net/guige8888811/article/details/133880362 其中还少一个知识点则是排序。而起初写了排序条件之后发现排序并不是按全表排的。代码如下: await mongodb.getConnection(attendanceRecord).aggregate([{$lookup: {from: userInf…

AI-漫画推文

🍨🍨项目源码 私信 🍨🍨技术选型 前端:Vue Vite Electron TS后端:Spring Boot MybatisPlus Redis Mysql

vox2vec论文速读

vox2vec: A Framework for Self-supervised Contrastive Learning of Voxel-Level Representations in Medical Images 摘要 本文介绍了 vox2vec——一种体素级表示的自监督学习 (SSL) 对比方法 vox2vec 表示由特征金字塔网络 (FPN&#xf…

Cascader 级联选择器 - 选择器最后一级数据为空

原因:将扁平数据转化为树形数据时,给每个项都添加了 children export const transList2Tree (list, rootPid) > {const result []list.forEach(item > {if (item.pid rootPid) {const children transList2Tree(list, item.id)item.children …

深圳风控建模岗薪资水平如何?

不管是学生还是工作的小伙伴,估计都对不同岗位工作几年的薪酬水平比较感兴趣。之前的文章提供爬取招聘网站,获取某类工作招聘信息的实现逻辑和代码。感兴趣可翻看批量爬取招聘网站上工作岗位的招聘信息。本文对爬取下来的信息进行清洗处理,以深圳风控建模岗为例,分析不同工…

Linux C++ 034-STL之谓词

Linux C 034-STL之谓词 本节关键字:Linux、C、谓词 相关库函数: 谓词概念 概念: 返回值为bool类型的仿函数称为谓词 如果operator()接受一个参数,那么叫做一元谓词 如果operator()接受两个参数,那么叫做二元谓词 一…

Unity绘制地图

首先在项目/Assets文件夹下创建一个Tiles文件夹 在层级下点击鼠标右键选择2D对象选择瓦片地图创建Tilemap。 选择地图素材 如果素材需要裁剪,在检查器Sprite模式选择多个,点击Sprite Editor,选择切 ,选择类型Grid By Cell Count,…

BoostCompass(建立正排索引和倒排索引模块)

阅读导航 一、模块概述二、编写正排索引和倒排索引模块✅安装 jsoncpp✅Jieba分词库的安装1. 代码基本框架2. 正排索引的建立3. 倒排索引的建立 三、整体代码⭕index.hpp 一、模块概述 这个模块我们定义了一个名为Index的C类,用于构建和维护一个文档索引系统。该系…

3D视觉技术

1. 简介 3D视觉是一个多学科相融合的技术,可以总结为:计算图形学计算机视觉人工智能3D视觉。3D视觉技术是通过3D摄像头采集视野空间内每个点位的三维座标信息,通过算法复原获取三维立体成像,不会轻易受到外界环境、复杂光线的影响…

Fiddler的安装和使用

Fiddler是一款强大的网络调试工具,可以帮助开发者进行网络请求和响应的调试和分析。以下是关于Fiddler的安装和使用的简要说明: 安装: 访问Fiddler的官方网站,下载对应版本的安装程序(一般选择经典版下载 - Fiddler Classic&…

【计算机毕业设计】停车场管理系统——后附源码

🎉**欢迎来到琛哥的技术世界!**🎉 📘 博主小档案: 琛哥,一名来自世界500强的资深程序猿,毕业于国内知名985高校。 🔧 技术专长: 琛哥在深度学习任务中展现出卓越的能力&a…

线程创建中的方法、属性情况?(企业真题)

线程创建中的方法、属性情况? start():①启动线程 ②调用线程的run() run():将线程要执行的操作,声明在run()中。 currentThread():获取当前执行代码对应的线程 getName(): 获取线程名 setName(): 设置线程名 sleep(long millis):静态方法,调…

pe格式从入门到图形化显示(八)-导入表

文章目录 前言一、什么是Windows PE格式中的导入表?二、解析导入表并显示1.导入表的结构2.解析导入表3.显示导入表 前言 通过分析和解析Windows PE格式,并使用qt进行图形化显示 一、什么是Windows PE格式中的导入表? 在Windows中&#xff0…

Harmony鸿蒙南向驱动开发-SDIO接口使用

功能简介 SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD卡,并且可以连接支持SDIO接口的其他设备。 SDIO接口定义了操作SDIO的通用…

python NLP数据集分割大文件

python NLP数据集分割大文件 NLP数据文件有时候特别大的文件,需要分割成N个小文件来处理 部分提取:可以提取N份,每份K行 全部分割:分割整个文件,每一份K行 import osdef split_file(filename, outdir,num_lines):&quo…