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

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

在软件开发中,单例设计模式(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.dtcms.com/a/106391.html

相关文章:

  • 一份关于近期推理模型研究进展的报告
  • PostgreSQL DDL 语句基本语法概览
  • 程序化广告行业(51/89):Cookie映射与移动设备ID映射解析
  • ARC缓存淘汰算法
  • 青少年编程与数学 02-015 大学数学知识点 03课题、概率论和数理统计
  • 探索Doris:日志分析的新宠,是否能取代老牌ES?
  • 使用PyInstaller打包Python项目
  • 蓝桥杯冲刺:一维前缀和
  • C语言的continue与break
  • web前端开发-JS
  • Python爬虫第3节-会话、Cookies及代理的基本原理
  • PCL RANSAC探测空间直线(指定方向)
  • Pyspark学习一:概述
  • ARM板 usb gadget hid 模拟键鼠
  • 基于 Jackson 的 JSON 工具类实现解析与设计模式应用
  • 网盘解析工具v1.3.1发布,希望能解决黑号问题吧
  • LTSPICE仿真电路:(二十四)MOS管推挽驱动电路简单仿真
  • 【idea】实用插件
  • Redis 03
  • HTML表单元素input
  • C++17更新内容汇总
  • CentOS 7 上安装 Hadoop 集群的详细教程
  • 华为2024年营收逼近历史峰值:终端业务复苏、智能汽车爆发式增长
  • Leetcode hot 100(day 3)
  • HDMI接口类型介绍
  • 在openharmony中部署helloworld应用(超详细)
  • 线段树,单点,区间修改查阅
  • 酶动力学预测工具CataPro安装教程
  • Rabbit:流加密的 “极速赛车手”
  • 单例模式与线程安全