Java 基础-30-单例设计模式:懒汉式与饿汉式

news2025/4/6 6:05:35

在软件开发中,单例设计模式(Singleton Design Pattern)是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式通常用于管理共享资源(如数据库连接池、线程池等)或需要全局唯一实例的场景。

本文将详细介绍两种常见的单例实现方式:懒汉式饿汉式,并分析它们的优缺点及适用场景。


1. 单例模式的核心要素

要实现单例模式,需要满足以下三个条件:

  1. 私有化构造方法:防止外部通过new关键字创建对象。
  2. 提供静态方法获取唯一实例:通过一个公共的静态方法返回唯一的实例。
  3. 保持单一实例:确保类中只有一个实例存在。

2. 饿汉式(Eager Initialization)

饿汉式是指在类加载时就立即创建实例。这种方式的特点是简单直接,但可能会造成资源浪费(如果实例从未被使用过)。

实现代码

public class SingletonEager {
    // 1. 私有化构造方法
    private SingletonEager() {
        System.out.println("SingletonEager instance created");
    }

    // 2. 在类加载时创建唯一的实例
    private static final SingletonEager instance = new SingletonEager();

    // 3. 提供公共的静态方法获取实例
    public static SingletonEager getInstance() {
        return instance;
    }
}

特点

  • 优点
    • 简单易懂,实现方便。
    • 线程安全(因为实例在类加载时就已经创建,不存在多线程竞争问题)。
  • 缺点
    • 如果实例从未被使用过,会浪费内存资源。
    • 不适合需要延迟加载的场景。

3. 懒汉式(Lazy Initialization)

懒汉式是指在第一次调用getInstance()方法时才创建实例。这种方式可以避免资源浪费,但需要注意线程安全问题。

实现代码(非线程安全版本)

public class SingletonLazy {
    // 1. 私有化构造方法
    private SingletonLazy() {
        System.out.println("SingletonLazy instance created");
    }

    // 2. 定义静态变量,但不立即初始化
    private static SingletonLazy instance;

    // 3. 提供公共的静态方法获取实例
    public static SingletonLazy getInstance() {
        if (instance == null) { // 第一次检查
            instance = new SingletonLazy(); // 创建实例
        }
        return instance;
    }
}

特点

  • 优点
    • 延迟加载,节省资源。
  • 缺点
    • 存在线程安全问题(多线程环境下可能创建多个实例)。
线程安全改进版(双重检查锁定)

为了解决线程安全问题,可以使用双重检查锁定(Double-Checked Locking)机制:

public class SingletonLazySafe {
    // 1. 私有化构造方法
    private SingletonLazySafe() {
        System.out.println("SingletonLazySafe instance created");
    }

    // 2. 使用volatile关键字保证可见性和禁止指令重排
    private static volatile SingletonLazySafe instance;

    // 3. 双重检查锁定
    public static SingletonLazySafe getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (SingletonLazySafe.class) {
                if (instance == null) { // 第二次检查
                    instance = new SingletonLazySafe();
                }
            }
        }
        return instance;
    }
}

特点

  • 优点
    • 延迟加载,节省资源。
    • 线程安全。
  • 缺点
    • 实现复杂度较高。

4. 对比:懒汉式 vs 饿汉式

特性饿汉式懒汉式
实例创建时机类加载时第一次调用getInstance()
资源占用可能浪费资源延迟加载,节省资源
线程安全性天然线程安全需额外处理(如双重检查锁定)
实现复杂度简单较复杂
适用场景实例一定会被使用且对性能要求高实例可能不会被使用或需延迟加载

5. 其他实现方式(扩展)

除了懒汉式和饿汉式,还有其他常见的单例实现方式,例如:

枚举单例

public enum SingletonEnum {
    INSTANCE;

    public void doSomething() {
        System.out.println("Doing something...");
    }
}
  • 优点:天然线程安全,防止反射攻击,简洁优雅。
  • 缺点:功能有限,不适合需要继承的场景。

静态内部类

public class SingletonInnerClass {
    private SingletonInnerClass() {}

    private static class SingletonHolder {
        private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();
    }

    public static SingletonInnerClass getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  • 优点:延迟加载,线程安全,性能较好。
  • 缺点:实现稍复杂。

6. 总结

  • 饿汉式适合于实例一定会被使用的场景,简单高效,但可能会浪费资源。
  • 懒汉式适合于实例可能不会被使用的场景,可以延迟加载,但需要注意线程安全问题。
  • 如果追求简洁和安全性,推荐使用枚举单例静态内部类实现。

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

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

相关文章

尚语翻译图册翻译|专业图册翻译|北京专业翻译公司推荐|专业文件翻译报价

内容概要 尚语翻译公司聚焦多语种产品图册翻译的竞价推广服务,通过行业垂直化运营构建差异化竞争力。其核心服务覆盖机械制造、医疗器械、电子元件三大领域,依托ISO 17100认证的翻译流程和Trados术语管理系统,实现技术文档的精准转化。为提升…

LeetCode 解题思路 30(Hot 100)

解题思路: 递归参数: 生成括号的对数 n、结果集 result、当前路径 path、左括号数 open、右括号数 close。递归过程: 当当前路径 path 的长度等于 n * 2 时,说明已经生成有效括号,加入结果集。若左括号数小于 n&…

Java EE(18)——网络原理——应用层HTTP协议

一.初识HTTP协议 HTTP(HyperText Transfer Protocol,超文本传输协议)是用于在客户端(如浏览器)和服务器之间传输超媒体文档(如HTML)的应用层协议。 HTTP协议发展至今发布了多个版本,其中1.0,1.…

强大而易用的JSON在线处理工具

强大而易用的JSON在线处理工具:程序员的得力助手 在当今的软件开发世界中,JSON(JavaScript Object Notation)已经成为了数据交换的通用语言。无论是前端还是后端开发,我们都经常需要处理、验证和转换JSON数据。今天&a…

Qt笔记----》不同环境程序打包

文章目录 概要1、windows环境下打包qt程序2、linux环境下打包qt程序2.1、程序目录2.2、创建一个空文件夹2.3、添加依赖脚本2.4、打包过程2.4.1、添加程序依赖库2.4.2、添加Qt相关依赖库 概要 qt不同运行环境下打包方式:windows/linux 1、windows环境下打包qt程序 …

企业服务器备份软件,企业服务器备份的方法有哪些?

企业服务器备份需综合考虑数据量、业务连续性要求(RTO/RPO)、合规性及成本等因素。以下是分场景的工具和方法指南: 一、备份软件推荐 1. 80KM备份软件 80KM备份软件可以进行很复杂的备份方式,也可以内网对内网备份、还能内网的…

html5炫酷图片悬停效果实现详解

html5炫酷图片悬停效果实现详解 这里写目录标题 html5炫酷图片悬停效果实现详解项目介绍技术栈核心功能实现1. 页面布局2. 图片容器样式3. 炫酷悬停效果缩放效果倾斜效果模糊效果旋转效果 4. 悬停文字效果5. 性能优化6. 响应式设计 项目亮点总结 项目介绍 本文将详细介绍如何使…

机器学习的一百个概念(5)数据增强

前言 本文隶属于专栏《机器学习的一百个概念》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…

在MCU工程中优化CPU工作效率的几种方法

在嵌入式系统开发中,优化 CPU 工作效率对于提升系统性能、降低功耗、提高实时性至关重要。Keil 作为主流的嵌入式开发工具,提供了多种优化策略,包括 关键字使用、内存管理、字节对齐、算法优化 等。本文将从多个方面介绍如何在 Keil 工程中优…

美团民宿 mtgsig 小程序 mtgsig1.2 分析

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向分析 cp execjs.compile(open(民…

(done) MIT6.824 Lecture 02 - RPC and Threads

知乎专栏:https://zhuanlan.zhihu.com/p/641105196 原视频:https://www.bilibili.com/video/BV16f4y1z7kn?spm_id_from333.788.videopod.episodes&vd_source7a1a0bc74158c6993c7355c5490fc600&p2 看知乎专栏 一、Why we choose go&#xff1f…

LayaAir3.3.0-beta.3重磅更新!Spine4.2、2D物理、UI系统、TileMap等全面升级!

正式版推出前,说明3.3的功能还没开发完。所以,又一大波更新来了~ 下面对重点更新进行说明。 Spine的重要更新 3.3.0-beta.3版本开始,新增了Spine 4.2 的运行时库,Spine动画上可以支持物理特性了。例如,下图右侧女孩在启…

【AI学习】机器学习算法

1,线性回归模型(Linear Regression):预测连续数值 寻找自变量(解释变量)与因变量(被解释变量)之间的线性关联关系,通过构建线性方程来对数据进行拟合和预测。即两个变量之间是一次函…

【渗透测试】Vulnhub靶机-FSoft Challenges VM: 1-详细通关教程

下载地址:https://www.vulnhub.com/entry/fsoft-challenges-vm-1,402/ 目录 前言 信息收集 目录扫描 wpscan扫描 修改密码 反弹shell 提权 思路总结 前言 开始前注意靶机简介,当第一次开机时会报apache错误,所以要等一分钟后重启才…

【区块链+ 房产建筑】山东省建筑产业互联网平台 | FISCO BCOS 应用案例

山东省建筑产业互联网平台(山东省弘商易盟平台)是基于区块链技术构建的分布式产业互联网平台, 旨在把各企业内部的供应链协同管理系统(包括采购或者SRM 系统, 以及销售或CRM 系统)利用区块链技术链接起来&a…

国家天文台携手阿里云,发布国际首个太阳大模型“金乌”

2025年4月1日,中国科学院国家天文台与阿里云共同宣布推出全球首个太阳物理大模型“金乌”,在太阳活动预测领域实现颠覆性突破——其针对破坏性最强的M5级太阳耀斑预报准确率高达91%,远超传统数值模型,标志着人类对太阳的认知迈入“…

数据结构(5)——栈

目录 前言 一、栈的概念及其结构 二、栈的实现 2.1说明 2.2动态栈结构体定义 2.3初始化 2.4销毁 2.5进(压)栈 2.6检验栈是否为空 2.7弹(出)栈 2.8栈的元素个数 2.9访问栈顶元素 三、运行 总结 前言 栈是一种常见的…

Css径向渐变 - radial-gradient

由background-image: radial-gradient(at 75% 7%, blue 0px, transparent 50%);引出: 一、径向渐变是什么 径向渐变是颜色从一个中心点向外扩散的变化过程。 二、radial-gradient 函数是什么 1、使用语法: background-image: radial-gradient(shape si…

理解激活函数,多个网络层之间如何连接

1. 激活函数如何在两个层之间作用 如果不在两个层之间添加激活函数,模型将无法学习非线性关系,表现出像线性模型一样的局限性。 LeakyReLU(0.2) 是一个激活函数,它的作用是对每一层的输出进行非线性转换。激活函数通常在神经网络中用于增加网…

HTML5 Canvas绘画板项目实战:打造一个功能丰富的在线画板

HTML5 Canvas绘画板项目实战:打造一个功能丰富的在线画板 这里写目录标题 HTML5 Canvas绘画板项目实战:打造一个功能丰富的在线画板项目介绍技术栈核心功能实现1. 画板初始化与工具管理2. 多样化绘画工具3. 事件处理机制 技术要点分析1. Canvas上下文优化…