Java 单例模式详解

article/2025/6/23 3:06:25

目录

1. 饿汉式(Eager Initialization)

2. 懒汉式(Lazy Initialization)

3. 懒汉式 + 同步锁(线程安全)

4. 双重检查锁(Double-Checked Locking)

5. 静态内部类(推荐)

6. 枚举(最佳实践)

单例模式的序列化与反序列化问题

单例模式适用场景

总结


单例模式是 Java 中最简单且最常用的设计模式之一,其核心思想是确保一个类只有一个实例,并提供全局访问点。下面分别详解 Java 中的单例模式:

1. 饿汉式(Eager Initialization)

特点:类加载时立即创建实例,线程安全。
缺点:不支持延迟加载,可能造成资源浪费。

public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {} // 私有构造函数public static Singleton getInstance() {return INSTANCE;}
}

2. 懒汉式(Lazy Initialization)

特点:首次调用时创建实例,支持延迟加载。
缺点:多线程环境下不安全。

public class Singleton {private static Singleton INSTANCE;private Singleton() {}public static Singleton getInstance() {if (INSTANCE == null) { // 多线程可能同时进入此判断INSTANCE = new Singleton();}return INSTANCE;}
}

3. 懒汉式 + 同步锁(线程安全)

特点:通过synchronized保证线程安全。
缺点:每次调用都加锁,性能开销大。

public class Singleton {private static Singleton INSTANCE;private Singleton() {}public static synchronized Singleton getInstance() { // 方法级同步if (INSTANCE == null) {INSTANCE = new Singleton();}return INSTANCE;}
}

4. 双重检查锁(Double-Checked Locking)

特点:线程安全且性能优化,仅首次创建时加锁。
关键点:使用volatile关键字禁止指令重排序。

public class Singleton {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;}
}

5. 静态内部类(推荐)

特点:线程安全、支持延迟加载,实现简洁。
原理:JVM 保证静态内部类的初始化线程安全。

public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

6. 枚举(最佳实践)

特点:线程安全、自动支持序列化机制、防止反射攻击。
推荐场景:需要绝对防止单例被破坏的场景。

public enum Singleton {INSTANCE;// 可以添加方法public void doSomething() {System.out.println("Singleton method called");}
}

单例模式的序列化与反序列化问题

如果单例类实现了Serializable接口,需添加readResolve()方法防止反序列化时创建新实例:

private Object readResolve() {return INSTANCE;
}

单例模式适用场景

  • 资源管理器(如数据库连接池、线程池)。
  • 配置文件管理。
  • 日志记录器。
  • GUI 中的窗口管理器。

总结

推荐使用静态内部类枚举实现单例模式:

  • 静态内部类:简洁、安全、支持延迟加载。
  • 枚举:防反射、防序列化攻击,写法优雅。

避免使用普通懒汉式,在多线程环境下需使用双重检查锁或更优方案


http://www.hkcw.cn/article/tuRiKGaOHy.shtml

相关文章

大模型应用开发之预训练

预训练是研发大语言模型的第一个训练阶段,通过在大规模语料上进行预训练,大语言模型可以获得通用的语言理解与生成能力,掌握较为广泛的世界知识,具备解决众多下游任务的性能潜力 一、数据预处理 1. 数据的收集 1)通…

属性映射框架-MapStruct

属性映射框架-MapStruct 文章目录 属性映射框架-MapStruct一、作用二、MapStruct 简介2.1 是什么2.2 竞品框架2.3 适合场景 三、入门案例3.1 项目需求3.2 代码实现 四、入门案例解析五、MapStruct 实战5.1 当属性正常映射时5.2 当某个属性要忽略映射5.3 当某个属性要求设置默认…

switch-case判断

switch-case判断 #include <stdio.h> int main() {int type;printf("请输入你的选择&#xff1a;\n");scanf("%d",&type);getchar();switch (type){case 1:printf("你好&#xff01;");break;case 2:printf("早上好&#xff01;…

德拜温度热容推导

目录 一、背景与基本假设 一、态密度的定义 二、从波矢空间出发 三、振动模式数与波矢体积关系 四、模式总数计算 五、态密度求导 六、德拜频率确定与归一化条件 二、内能表达式的推导 三、态密度代入与变量替换 四、求比热容 五、低温时&#xff08;&#xff09; …

Android Framework层RenderThread指令队列深度调试实战指南

简介 在移动应用开发过程中,UI渲染性能优化是提升用户体验的关键环节。Android的RenderThread作为硬件加速渲染的核心线程,其指令队列的处理效率直接影响着应用的流畅度。本篇文章将深入探讨如何在Android Framework层对RenderThread指令队列进行调试和优化,帮助开发者解决…

BLE协议全景图:从0开始理解低功耗蓝牙

BLE(Bluetooth Low Energy)作为一种针对低功耗场景优化的通信协议,已经广泛应用于智能穿戴、工业追踪、智能家居、医疗设备等领域。 本文是《BLE 协议实战详解》系列的第一篇,将从 BLE 的发展历史、协议栈结构、核心机制和应用领域出发,为后续工程实战打下全面认知基础。 …

深入理解C#异步编程:原理、实践与最佳方案

在现代软件开发中&#xff0c;应用程序的性能和响应能力至关重要。特别是在处理I/O密集型操作&#xff08;如网络请求、文件读写、数据库查询&#xff09;时&#xff0c;传统的同步编程方式会导致线程阻塞&#xff0c;降低程序的吞吐量。C# 的异步编程模型&#xff08;async/aw…

如何查看电脑电池性能

检查电脑电池性能的方法如下&#xff1a; 按下winR键&#xff0c;输入cmd回车&#xff0c;进入命令行窗口 在命令行窗口输入powercfg /batteryreport 桌面双击此电脑&#xff0c;把刚刚复制的路径粘贴到文件路径栏&#xff0c;然后回车 回车后会自动用浏览器打开该报告 红…

高考加油!UI界面生成器!

这个高考助力标语生成器具有以下特点&#xff1a; 视觉设计&#xff1a;采用了蓝色为主色调&#xff0c;搭配渐变背景和圆形装饰元素&#xff0c;营造出宁静而充满希望的氛围&#xff0c;非常适合高考主题。 标语生成&#xff1a;内置了超过 100 条精心挑选的高考加油标语&a…

fork函数小解

学了好久终于搞懂fork函数的一些作用 1. fork函数作用&#xff1a;用于创建新的子进程 这是fork最根本的功能&#xff0c;在父进程里创建新的子进程、 但是创建新的子进程之后呢&#xff1f; 子进程和父进程的关系是什么样的&#xff1f; 为什么fork得到的子进程返回值为0&am…

5月31日day41打卡

简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 → Batch…

配置前端控制器

一、DispatcherServlet 详解 在使用 Spring MVC 框架构建 Web 应用时&#xff0c;DispatcherServlet是整个请求处理流程的核心。本文将深入解析DispatcherServlet的作用、工作原理及其在 Spring MVC 架构中的关键地位。 1.DispatcherServlet 是什么&#xff1f; DispatcherS…

使用PowerBI个人网关定时刷新数据

使用PowerBI个人网关定时刷新数据 PowerBI desktop连接mysql&#xff0c;可以设置定时刷新数据或在PowerBI服务中手动刷新数据,步骤如下&#xff1a; 第一步&#xff1a; 下载网关。以个人网关为例&#xff0c;如图 第二步&#xff1a; 双击网关&#xff0c;点击下一步&…

Dest建筑能耗模拟仿真功能简介

Dest建筑能耗模拟仿真功能简介 全球建筑能耗占终端能源消费的30%以上&#xff0c;掌握建筑能耗模拟是参与绿色建筑认证&#xff08;如LEED、WELL&#xff09;、超低能耗设计、既有建筑节能改造的必备能力。DEST作为国内主流建筑能耗模拟工具&#xff0c;广泛应用于设计院、咨询…

Vue2+Vuex通过数组动态生成store数据(分组模式)

在项目开发中,将数据集中存储在Vuex的store中,能便于数据的统一管理和维护。开发者可以在一个地方对数据进行操作和更新,以避免在组件中分散管理数据带来的混乱和复杂性。 对于状态数据较多情况下,界面操作数据又是数组结构,因业务需求,数组内每个元素都需要单独定义一个…

生成式AI模型学习笔记

文章目录 生成式AI模型1. 定义2. 生成式模型与判别式模型3. 深度生成式模型的类型3.1 能量模型3.2 变分自编码3.2.1 变分自编码器&#xff08;Variational Autoencoder, VAE&#xff09;简介3.2.2 代码示例&#xff08;以 PyTorch 为例&#xff09; 3.3 生成对抗网络3.4 流模型…

DAY 16 numpy数组与shap深入理解

一、NumPy 数组基础笔记 1. 理解数组的维度 &#xff08;Dimensions&#xff09; NumPy 数组的维度 &#xff08;Dimension&#xff09; 或称为 轴 &#xff08;Axis&#xff09; 的概念&#xff0c;与我们日常理解的维度非常相似。 直观判断&#xff1a; 数组的维度层数通常…

Maven 安装与配置指南(适用于 Windows、Linux 和 macOS)

Apache Maven 是一款广泛应用于 Java 项目的项目管理和构建工具。 本文提供在 Windows、Linux 和 macOS 系统上安装与配置 Maven 的详细步骤&#xff0c;旨在帮助开发者快速搭建高效的构建环境。 一、前置条件&#xff1a;安装 Java Development Kit (JDK) Maven 依赖于 Java …

Java对象克隆:从浅到深的奥秘

浅克隆与深克隆在Java中的应用及区别 核心概念 浅克隆 复制对象时仅克隆基本数据类型字段&#xff0c;引用类型字段共享原对象引用。实现方式&#xff1a; class Person implements Cloneable {String name;Address address; // 引用类型字段Overrideprotected Object clone…

【HW系列】—日志介绍

文章目录 一、日志介绍二、Apache日志详解1. 日志存放位置2. 日志类型3. 日志级别4. 常用日志分析命令&#xff08;Linux环境&#xff09; 三、IIS日志详解四、日志分析工具&#xff1a;360星图 一、日志介绍 为什么要使用日志 故障诊断&#xff1a;快速定位系统错误根源安全审…