当前位置: 首页 > news >正文

技术成神之路:设计模式(一)单例模式

在软件设计中,有时我们希望某个类的实例始终是唯一的,即无论在何处访问这个类,都能够得到同一个实例。单例模式(Singleton Pattern)就是为了解决这个问题而产生的。单例模式确保一个类只有一个实例,并提供一个全局访问点。

1.定义


单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。其主要思想是将类的构造函数私有化,并通过一个静态方法来控制实例的创建和访问。

2.常见实现方式


单例模式有多种实现方式,下面介绍几种常见的实现方式:

2.1饿汉式(Eager Initialization)

饿汉式是在类加载时就创建实例,这样可以确保线程安全,并且在类首次使用前完成实例化。

示例代码:

public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {// 私有构造函数,防止外部实例化}public static Singleton getInstance() {return INSTANCE;}
}

优点:简单,易于理解,线程安全
缺点:类加载时即创建实例,可能造成资源浪费

如果你一定会使用该类,这种方式无疑是最简单的方法

2.2 懒汉式(Lazy Initialization)

懒汉式是在第一次调用 getInstance() 方法时创建实例。这种方式避免了饿汉式的资源浪费问题。

示例代码:

public class Singleton {private static Singleton instance;private Singleton() {// 私有构造函数,防止外部实例化}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

优点:实现简单,延迟实例化,避免资源浪费
缺点:使用了 synchronized,在高并发情况下性能可能较差

每次调用getInstance()都会进行同步检查,这样会消耗不必要的资源,不推荐使用

2.3双重检查锁(Double-Checked Locking)

双重检查锁在懒汉式的基础上,通过减少使用 synchronized 来提高性能。

示例代码:

public class Singleton {// volatile关键字确保多线程下的可见性和有序性(禁止字节码重排)private static volatile Singleton instance;private Singleton() {// 私有构造函数,避免外部直接实例化}public static Singleton getInstance() {if (instance == null) {  // 第一次检查synchronized (Singleton.class) {if (instance == null) {  // 第二次检查instance = new Singleton();  // 实例化}}}return instance;  // 返回实例}
}

优点:延迟实例化,提高了性能
缺点:实现复杂,容易出错

同步代码块含义:因为可能会有多个线程同时通过了第一次检查,在进入同步块之后,再次检查可以确保只有一个线程创建实例,最大限度地在提升性能的条件下保证了线程安全。

emm… 个人不喜欢这种笨重写法

2.4 静态内部类(Static Inner Class)

这种方式使用了类加载机制来确保线程安全,同时实现了延迟加载。

示例代码:

public class Singleton {private Singleton() {// 私有构造函数,防止外部实例化}// 静态内部类,利用类加载机制保证线程安全且延迟加载private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

优点:延迟实例化,线程安全,实现简单
缺点:无法传递外部参数

这时候就会有同学要问了,何为类加载机制,问的好,所谓类加载机制就算:JVM 在加载类的过程中,静态内部类 SingletonHolder 中的静态变量 INSTANCE 只会被实例化一次,由JVM保证其线程安全性,所以在多线程环境下可以安全地使用。

2.5 枚举(Enum)

这种方法是Effective Java作者Joshua Bloch推荐的单例实现方式之一,它解决了传统单例模式实现中的一些问题,比如序列化、反射攻击等。

示例代码:

public enum Singleton {INSTANCE;public void doSomething() {// 业务方法}
}

优点:简洁,线程安全,防止反序列化破坏单例
缺点:无法灵活控制实例化过程

使用方法:

Singleton.INSTANCE.doSomething();

特点和优势

  1. 线程安全性:
    枚举类型的实例创建是线程安全的,JVM在加载枚举类型时会通过类加载器保证只实例化一次。因此,多线程环境下也能保证单例的唯一性。

  2. 防止反射攻击:
    枚举类型的实例创建是由JVM控制的,因此无法通过反射来创建枚举类的实例。这样可以防止反射攻击,即使是在枚举类中添加了私有构造函数也不例外。

  3. 防止序列化问题:
    Java枚举类型在序列化和反序列化时会自动处理,确保在序列化和反序列化过程中都是单例的。

  4. 简洁且高效:
    枚举实现单例模式非常简洁,只需声明一个枚举类型即可,不需要额外的代码来保证线程安全和单例特性。

3.单例模式的注意事项


  • 线程安全:确保在多线程环境下一个类只有一个实例。
  • 延迟加载:尽量避免在类加载时就实例化,除非明确知道实例一定会被使用。
  • 防止反射攻击:通过在构造函数中添加判断来防止反射创建多个实例。
  • 防止反序列化破坏单例:在实现 Serializable 接口时,提供 `readResolve 方法。

4.总结


五种创建单例的方式,大家按需选择,核心思想都是确保一个类只有一个实例,并提供全局访问点,没有最好的,只有最适合的,理解不同实现方式的优缺点,可以帮助我们在实际开发中选择最合适的方案。

相关文章:

技术成神之路:设计模式(一)单例模式

在软件设计中,有时我们希望某个类的实例始终是唯一的,即无论在何处访问这个类,都能够得到同一个实例。单例模式(Singleton Pattern)就是为了解决这个问题而产生的。单例模式确保一个类只有一个实例,并提供一…...

四、(3)补充beautifulsoup、re正则表达式、标签解析

四、(3)补充beautifulsoup、re正则表达式、标签解析 beautifulsoupre正则表达式正则提取标签解析 beautifulsoup 补充关于解析的知识 还需要看爬虫课件 如何定位文本或者标签,是整个爬虫中非常重要的能力 无论find_all(&#xff…...

Vscode快捷键崩溃

Vscode快捷键崩溃 Linux虚拟机下使用vscode写代码【ctrlA,CtrlC,CtrlV】等快捷键都不能使用,还会出现“NO text insert“等抽象的指令,问题就是不知道什么时候装了一个VIM插件,让他滚出电脑》》》...

Spring Boot中的开发工具与插件推荐

Spring Boot中的开发工具与插件推荐 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们来聊聊Spring Boot中的开发工具与插件推荐。Spring Boot作为一种简…...

qt6 获取百度地图(一)

需求分析: 要获取一个地图, 需要ip 需要根据ip查询经纬度 根据经纬度查询地图 另外一条线是根据输入的地址 查询ip 根据查询到的ip查地图‘ 最后,要渲染地图 上面这这些动作,要进行http查询: 为此要有三个QNet…...

overlap的uORF对TE的抑制程度为什么显著高于non-overlap的uORF

在翻译调控中,上游开放阅读框(uORFs)对主开放阅读框(main ORF)的抑制效果有很大差异,尤其是重叠的uORFs(overlap uORFs)通常比非重叠的uORFs(non-overlap uORFs&#xff…...

面向高精度导航定位领域的UM980RTK定位模块

UM980 是和芯星通自主研发的新一代 BDS/GPS/GLONASS/Galileo/QZSS 全系统全频高精度 RTK 定位模块,基于和芯星通自主研发的新一代射频基带及高精度算法一体化GNSS SoC 芯片—NebulasIV 设计。可同时跟踪 BDS, GPS, GLONASS, Galileo, QZSS, NavIC, SBAS, L-Band* 等…...

145-四路16位125Msps AD FMC子卡模块

一、概述 该板卡可实现4路16bit 125Msps AD 功能,是xilinx开发板设计的标准板卡。FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设备中,特别是在xilinx公司的所有开发板中都使用。该AD,DA子卡模块就专门针对xilinx开发…...

服务器被劫持

当服务器被劫持时,可以采取一系列措施来修复和加强安全防护,确保服务器的安全性和数据的完整性。以下是一些建议的步骤和策略:12 确认服务器被劫持:首先需要确认服务器是否被劫持。这可以通过检查服务器的日志、网络流量、以及任…...

康姿百德磁性床垫好不好,效果怎么样靠谱吗

康姿百德典雅款床垫,打造舒适睡眠新体验 康姿百德床垫是打造舒适睡眠新体验的首选,其设计能够保护脊椎健康,舒展脊椎,让您享受一夜好眠。康姿百德床垫的面料选择也非常重要,其细腻亲肤的针织面料给您带来柔软舒适的触…...

[吃瓜教程]南瓜书第5章神经网络

1.M-P神经元 M-P神经元,全称为McCulloch-Pitts神经元,是一种数学模型,用于模拟生物神经元的功能。这个模型是由Warren McCulloch和Walter Pitts在1943年提出的。它是人工智能和计算神经科学领域中非常重要的早期模型。 M-P神经元接收n个输入…...

装饰模式解析:基本概念和实例教程

目录 装饰模式装饰模式结构装饰模式应用场景装饰模式优缺点练手题目题目描述输入描述输出描述题解 装饰模式 装饰模式,又称装饰者模式、装饰器模式,是一种结构型设计模式,允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行…...

211.xv6——3(page tables)

在本实验室中,您将探索页表并对其进行修改,以简化将数据从用户空间复制到内核空间的函数。 开始编码之前,请阅读xv6手册的第3章和相关文件: kernel/memlayout.h,它捕获了内存的布局。kernel/vm.c,其中包含…...

yum使用报错:ImportError: /lib64/libxml2.so.2: file too short

系统版本:Rocky 8.10 报错信息: Traceback (most recent call last):File "/usr/lib64/python3.6/site-packages/libdnf/error.py", line 14, in swig_import_helperreturn importlib.import_module(mname)File "/usr/lib64/python3.6/i…...

【Android面试八股文】你是怎么保证Android设备的时间与服务器时间同步的?(使用NTP和TrueTime方案)

文章目录 一、网络时间协议(NTP)二、使用网络时间协议(NTP)2.1 使用系统提供的 NTP 服务器2.2 使用TrueTime2.2.1 引入TrueTime库2.2.2 初始化 TrueTime2.2.3 用法2.2.4 使用 TrueTime 获取时间2.2.4 自动更新时间2.2.5 注意事项二. 使用 HTTP 请求获取服务器时间2.1. 发送…...

解决Python爬虫开发中的数据输出问题:确保正确生成CSV文件

引言 在大数据时代,爬虫技术成为获取和分析网络数据的重要工具。然而,许多开发者在使用Python编写爬虫时,常常遇到数据输出问题,尤其是在生成CSV文件时出错。本文将详细介绍如何解决这些问题,并提供使用代理IP和多线程…...

SCI一区TOP|徒步优化算法(HOA)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年,SO Oladejo受到徒步旅行启发,提出了徒步优化算法(Hiking Optimization Algorithm, HOA)。 2.算法原理 2.1算法思想 HOA灵感来自于…...

Android的activity广播无法接收,提示process gone or crashing原因有可能是那些?

当Android的Activity无法接收广播,并且收到“process gone or crashing”的提示时,可能的原因有多种。以下是一些常见的原因和排查步骤: Activity生命周期问题: 如果Activity在广播发送之前就已经被销毁(例如&#xf…...

如何将等保2.0的要求融入日常安全运维实践中?

等保2.0的基本要求 等保2.0是中国网络安全领域的基本国策和基本制度,它要求网络运营商按照网络安全等级保护制度的要求,履行相关的安全保护义务。等保2.0的实施得到了《中华人民共和国网络安全法》等法律法规的支持,要求相关行业和单位必须按…...

51单片机嵌入式开发:STC89C52环境配置到点亮LED

STC89C52环境配置到点亮LED 1 环境配置1.1 硬件环境1.2 编译环境1.3 烧录环境 2 工程配置2.1 工程框架2.2 工程创建2.3 参数配置 3 点亮一个LED3.1 原理图解读3.2 代码配置3.3 演示 4 总结 1 环境配置 1.1 硬件环境 硬件环境采用“华晴电子”的MINIEL-89C开发板,这…...

源代码加密:保护你的数字宝藏

在当今日益复杂的网络安全环境中,源代码作为企业的核心知识产权,其安全保护显得尤为重要。传统的源代码加密方法虽能提供一定的保护,但在应对新型威胁和复杂场景时,往往显得力不从心。而SDC沙盒技术的出现,为源代码加密…...

Jackson库使用教程

1. Jackson概述 定义: Jackson是一个基于Java的开源JSON解析工具,用于Java对象与JSON数据的互相转换。示例JSON:{"author": "一路向北_Coding","age": 20,"hobbies": ["coding", "leetcode", "r…...

汉王、绘王签字版调用封装

说明 需要配合汉王或绘王签字版驱动以及对应的sdk服务使用 constants.js //汉王、绘王sdk websocket连接地址 export const WS_URLS {1:ws://127.0.0.1:29999, //汉王2:ws://127.0.0.1:7181, }export const COMMAND1 {1: {HWPenSign: "HWStartSign",nLogo: "…...

如何在TikTok上获得更多观看量:12个流量秘诀

TikTok作为热门海外社媒,在跨境出海行业中成为新兴的推广渠道,但你知道如何让你的TikTok赢得更多关注次数吗?如果您正在寻找增加 TikTok 观看次数的方法,接下来这12种策略,你需要一一做好! 1. 在内容中添加…...

vue模板语法v-html

模板语法v-html vue使用一种基于HTML的模板语法,使我们能够声明式的将其组件实例的数据绑定到呈现的DOM上,所有的vue模板都是语法层面的HTML,可以被符合规范的浏览器和HTML解释器解析。 一.文本插值 最基本的数据绑定形式是文本插值&#…...

13 Redis-- 数据一致性模型、MySQL 和 Redis 的数据一致性

数据一致性模型 根据一致性的强弱分类,可以将一致性模型按以下顺序排列: 强一致性 > 最终一致性 > 弱一致性 数据一致性模型一般用于分布式系统中,目的是定义多个节点间的同步规范。 在这里,我们将其引入数据库和缓存组…...

启动Nuxt-hub-starter: Failed to initialize wrangler bindings proxy write EOF

重新安装 node.js 这样做可以确保下载到了适合的 Windows 框架、Chocolatey(一款Windows包管理工具)、Python 等资源。 这个错误与Node版本、pnpm/yarn 的版本无关! Node.js — Download Node.js (nodejs.org)...

技术驱动旅游创新!深度解析景区导览小程序的地图渲染与AR导航技术

随着现代生活节奏的加快,人们在外出旅游时更倾向于轻便出行,携带导览地图已成为过去。然而,面对景区广阔的面积和众多景点,游客常常感到迷茫,难以快速定位到自己所需的地点。景区导览小程序让游客只需搜索景区名称&…...

二叉树之遍历

二叉树之遍历 二叉树遍历遍历分类前序遍历流程描述代码实现 中序遍历流程描述代码实现 后序遍历流程描述代码实现 层次遍历流程描述代码实现 总结 二叉树遍历 遍历分类 遍历二叉树的思路有 4 种,分别是: 前序遍历二叉树,有递归和非递归两种…...

【经验贴】如何做好自己的职业规划(技术转项目经理)

我有几个问题想问大家 第一,你了解自己吗?你知道自己想要是什么吗?你了解自己的优势劣势吗? 第二,你了解这个行业吗?你知道这个行业是如何发展起来的吗?你了解这个行业的背景吗?你…...