【设计模式】单例模式详解及应用实例
单例模式(Singleton Pattern)
是一种创建型设计模式,保证一个类在整个程序的生命周期中只有一个实例,并提供一个全局访问点。单例模式广泛用于需要全局唯一实例的场景,比如数据库连接池、日志对象、线程池等。
单例模式的特点
- 唯一性:确保一个类只有一个实例。
- 延迟实例化:通常使用懒加载机制,即在第一次使用时才创建实例。
- 全局访问:提供一个全局访问点供外部获取该实例。
单例模式的实现方式
单例模式有多种实现方式,常见的有以下几种:
1. 懒汉式(Lazy Initialization)
懒汉式的单例模式是延迟初始化的,实例在第一次使用时才创建。这种方式的缺点是线程不安全。
public class SingletonLazy {private static SingletonLazy instance;// 私有化构造函数,防止外部实例化private SingletonLazy() {}// 获取单例对象的静态方法public static SingletonLazy getInstance() {if (instance == null) {instance = new SingletonLazy();}return instance;}
}
缺点: 懒汉式在多线程环境下可能会创建多个实例,因为线程可能会同时通过 if (instance == null)
条件。
2. 线程安全的懒汉式(Synchronized Method)
为了在多线程环境下保证实例的唯一性,可以使用 synchronized
关键字使方法同步。
public class SingletonLazyThreadSafe {private static SingletonLazyThreadSafe instance;private SingletonLazyThreadSafe() {}// 同步方法保证线程安全public static synchronized SingletonLazyThreadSafe getInstance() {if (instance == null) {instance = new SingletonLazyThreadSafe();}return instance;}
}
缺点: 虽然线程安全,但由于 synchronized
关键字的使用,每次调用 getInstance
都会产生一定的性能开销。
3. 双重检查锁定(Double-Checked Locking)
双重检查锁定在性能和线程安全之间做了折中。通过在实例初始化前后都进行检查,减少同步的开销。
public class SingletonDCL {// volatile 保证变量的可见性和有序性private static volatile SingletonDCL instance;private SingletonDCL() {}public static SingletonDCL getInstance() {if (instance == null) { // 第一次检查synchronized (SingletonDCL.class) {if (instance == null) { // 第二次检查instance = new SingletonDCL();}}}return instance;}
}
优点: 在多线程环境中高效且线程安全。
4. 静态内部类(Static Inner Class)
利用 Java 的类加载机制实现懒加载,静态内部类方式在类加载时不会立即实例化,而是在调用 getInstance()
时才加载内部类并创建实例。
public class SingletonStaticInnerClass {private SingletonStaticInnerClass() {}// 静态内部类持有 Singleton 的唯一实例private static class SingletonHolder {private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();}public static SingletonStaticInnerClass getInstance() {return SingletonHolder.INSTANCE;}
}
优点: 线程安全,且没有性能开销,推荐使用。
5. 枚举(Enum Singleton)
使用枚举实现单例是一种比较优雅的方式,因为 Java 枚举本身是线程安全的,并且只能有一个实例。
public enum SingletonEnum {INSTANCE;public void someMethod() {// 业务逻辑}
}
优点: 实现简单,枚举保证了线程安全且防止了反序列化破坏单例。
单例模式使用场景
- 配置类:当一个类只需要一个实例来提供全局配置时,比如读取配置文件的类。
- 数据库连接池:只需要一个连接池对象来管理数据库连接。
- 日志类:应用程序中通常需要一个全局的日志管理类。
- 线程池:应用程序只需要一个线程池来管理线程。
单例模式的使用技巧
-
防止反射破坏单例: 通过私有化构造器的方式可以阻止外部类直接使用
new
创建实例,但通过反射可以访问私有构造器破坏单例。为了解决这个问题,可以在构造器内加一个判断:private Singleton() {if (instance != null) {throw new RuntimeException("单例模式被破坏");} }
-
防止序列化破坏单例: 如果单例类实现了
Serializable
接口,在反序列化时可能会创建新的实例。为了解决这个问题,可以在类中实现readResolve
方法:private Object readResolve() {return instance; }
-
线程安全优化: 双重检查锁定(DCL)方式在保证线程安全的前提下,提高了性能,是多线程环境下常用的实现方式。
-
枚举单例推荐: 使用枚举实现单例模式可以简化代码,保证线程安全,并且防止反射和序列化破坏单例,因此被认为是最推荐的方式。
单例模式的实际实例
假设我们需要一个日志管理器,该管理器只允许创建一个实例,并能通过全局访问点进行日志记录。
public class LoggerSingleton {private static LoggerSingleton instance;private LoggerSingleton() {}// 双重检查锁定获取单例实例public static LoggerSingleton getInstance() {if (instance == null) {synchronized (LoggerSingleton.class) {if (instance == null) {instance = new LoggerSingleton();}}}return instance;}public void log(String message) {System.out.println("Log: " + message);}
}public class Main {public static void main(String[] args) {LoggerSingleton logger = LoggerSingleton.getInstance();logger.log("This is a singleton logger.");}
}
总结
- 单例模式提供了确保类实例唯一的有效方案,适用于全局共享资源。
- 常见实现方式包括懒汉式、双重检查锁定和静态内部类等。
- 推荐使用枚举实现单例,因为它天然防止了反射和序列化破坏单例的风险。
相关文章:
【设计模式】单例模式详解及应用实例
单例模式(Singleton Pattern)是一种创建型设计模式,保证一个类在整个程序的生命周期中只有一个实例,并提供一个全局访问点。单例模式广泛用于需要全局唯一实例的场景,比如数据库连接池、日志对象、线程池等。 单例模式…...

学习图解算法 使用C语言
图解算法 使用C语言 也就是通过C语言实现各种算法 链接:百度云盘 提取码:1001...
基于Netty实现TCP客户端:封装断线重连、连接保持
文章目录 引言I 基于Netty实现TCP客户端基于 Netty 创建客户端 时序图封装思路NettyClient 封装II 客户端的断线重连本质使用过程中断线重连重试策略III 心跳机制心跳检测处理器心跳机制实现逻辑IV 同步等待消息返回V 工具ForkJoinPoolByteConvertUtilsee also处理假死把handle…...

基于形状记忆聚合物的折纸超结构
公众号端文章: 基于SMP的折纸超结构https://mp.weixin.qq.com/s?__bizMzkwMjc0MTE3Mw&mid2247484016&idx4&sn16f8d4aaaff76d776cec19bc0adbdd3b&chksmc0a1afaaf7d626bc0457d9cc4ba1b38424c2aad71ffec548715e47f5611cf00f10d5a511f3b3#rd 折…...

前端用html写excel文件直接打开
源码 <html xmlns:o"urn:schemas-microsoft-com:office:office" xmlns:x"urn:schemas-microsoft-com:office:excel" xmlns"http://www.w3.org/TR/REC-html40"> <head><meta charset"UTF-8"><!--[if gte mso 9]&…...

FastText 和 Faiss 的初探了解
概览 大模型目前已经是如火如荼的程度,各个大厂都有推出面向大众的基础大模型,同时诸多行业也有在训练专有大模型,而大模型的发展由来却是经过多年从文本检索生成、深度学习、自然语言处理,在Transformer架构出来后,才…...

微服务保护学习笔记(五)Sentinel授权规则、获取origin、自定义异常结果、规则持久化
文章目录 前言4 授权规则4.1 基本原理4.2 获取origin4.3 配置授权规则 5 自定义异常结果6 规则持久化 前言 微服务保护学习笔记(一)雪崩问题及解决方案、Sentinel介绍与安装 微服务保护学习笔记(二)簇点链路、流控操作、流控模式(关联、链路) 微服务保护学习笔记(三)流控效果(…...

YOLOv8目标检测模型——遥感小目标检测经验分享
小目标检测——YOLOV8 一、引言 背景介绍 (1)目标检测的重要性 目标检测在许多领域都具有极其重要的作用。在自动驾驶中,目标检测能够识别道路上的障碍物和行人,确保行车安全。在视频监控中,目标检测能够实时发现异…...

构建响应式 Web 应用:Vue.js 基础指南
构建响应式 Web 应用:Vue.js 基础指南 一 . Vue 的介绍1.1 介绍1.2 好处1.3 特点 二 . Vue 的快速入门2.1 案例 1 : 快速搭建 Vue 的运行环境 , 在 div 视图中获取 Vue 中的数据2.2 案例 2 : 点击按钮执行 vue 中的函数输出 vue 中 data 的数据2.3 小结 三 . Vue 常…...

计算机毕业设计选题推荐-在线投票系统-Java/Python项目实战
✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

【C/C++】程序的构建(编译)过程概述
🦄个人主页:小米里的大麦-CSDN博客 🎏所属专栏:C_小米里的大麦的博客-CSDN博客 🎁代码托管:C: 探索C编程精髓,打造高效代码仓库 (gitee.com) ⚙️操作环境:Visual Studio 2022 目录 一、前言 二、预处理(Preprocessi…...

ElasticSearch-2-核心语法集群高可用实战-Week2
ES批量操作 1.批量获取文档数据 这里多个文档是指,批量操作多个文档,搜索查询文档将在之后的章节讲解 批量获取文档数据是通过_mget的API来实现的 (1)在URL中不指定index和type 请求方式:GET 请求地址:_mget 功能说明 &#…...

STM的CAN通信学习
显性电平:0 隐性电平:1 一、帧结构 1.帧类型 1)数据帧:发送设备主动发送数据(广播式) 2)请求帧:接收设备主动请求数据(请求式) 2.帧结构 1ÿ…...

【高等数学学习记录】函数
【高等数学&学习记录】函数 从事测绘工作多年,深刻感受到基础知识的重要及自身在这方面的短板。 为此,打算重温测绘工作所需基础知识。练好基本功,为测绘工作赋能。 1 知识点 1.1 函数 设数集 D ⊂ R D\subset R D⊂R,称映射…...

【springboot过ingress后无法获取X-Forwarded-For头信息】
springboot过ingress后无法获取X-Forwarded-For头信息 一、现象结论修改步骤ingressspringboot 排查流程本文参考 一、现象 项目使用spring boot 2.7.18,有个新需求是校验X-Forwarded-For头的所有来源ip合法性,线上环境出现取不到X-Forwarded-For头的问…...

表格标记<table>
一.表格标记、 1table:表格标记 2.caption:表单标题标记 3.tr:表格行标记 4.td:表格中数据单元格标记 5.th:标题单元格 table标记是表格中最外层标记,tr表示表格中的行标记,一对<tr>表示表格中的一行,在<tr>中可…...

Rust练手项目,写个有趣的小工具定时从一言网获取一段有趣的话并推送通知
Rust练手项目,写个有趣的小工具 代码 继续练习Rust, 写个小工具定时从一言网获取一段有趣的话并提示,如下 练习以下Rust点 并发编程 Mutex, Arc指针使用HTTP请求Windows Gui 代码 Cargo.toml [package] name "funny_word" edition "20…...

【隐私计算】Paillier半同态加密算法
一、何为同态加密(HE)? HE是一种特殊的加密方法,它允许直接对加密数据执行计算,如加法和乘法,而计算过程不会泄露原文的任何信息。计算的结果仍然是加密的,拥有密钥的用户对处理过的密文数据进…...
判断数字的奇偶[中秋快乐~]
题目描述 给定一个整数 n,编写程序判断数字 n 是奇数还是偶数,是奇数则输出 “odd”,偶数则输出 “even”。 输入格式 一行,一个整数 n。 输出格式 一行,如果 n 是奇数则输出 “odd”; 如果 nn 是偶数则输出 “even”。 样例…...
文件操作及重定向详解
1、linux下一切皆文件: 在linux中,一切皆文件是一个重要的概念,用于描述linux操作系统中所有资源和设备都以文件的形式进行访问和处理。 这个概念可以理解为,无论是硬盘上的文件、网卡、设备、进程等,都被抽象为文件的形式存在。在linux系统中,通…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...

数据挖掘是什么?数据挖掘技术有哪些?
目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...
Cursor AI 账号纯净度维护与高效注册指南
Cursor AI 账号纯净度维护与高效注册指南:解决限制问题的实战方案 风车无限免费邮箱系统网页端使用说明|快速获取邮箱|cursor|windsurf|augment 问题背景 在成功解决 Cursor 环境配置问题后,许多开发者仍面临账号纯净度不足导致的限制问题。无论使用 16…...

性能优化中,多面体模型基本原理
1)多面体编译技术是一种基于多面体模型的程序分析和优化技术,它将程序 中的语句实例、访问关系、依赖关系和调度等信息映射到多维空间中的几何对 象,通过对这些几何对象进行几何操作和线性代数计算来进行程序的分析和优 化。 其中࿰…...
SpringCloud优势
目录 完善的微服务支持 高可用性和容错性 灵活的配置管理 强大的服务网关 分布式追踪能力 丰富的社区生态 易于与其他技术栈集成 完善的微服务支持 Spring Cloud 提供了一整套工具和组件来支持微服务架构的开发,包括服务注册与发现、负载均衡、断路器、配置管理等功能…...
mcts蒙特卡洛模拟树思想
您这个观察非常敏锐,而且在很大程度上是正确的!您已经洞察到了MCTS算法在不同阶段的两种不同行为模式。我们来把这个关系理得更清楚一些,您的理解其实离真相只有一步之遥。 您说的“select是在二次选择的时候起作用”,这个观察非…...