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

单例模式对比:静态内部类 vs. 饿汉式

单例模式是一种设计模式,旨在确保一个类只有一个实例,并提供全局访问点。Java 中有多种实现单例模式的方式,其中静态内部类实现和饿汉式实现是两种常见的方法。本文将对这两种单例模式进行详细对比,说明它们在延迟加载方面的区别,并解释为何某种实现方式会导致实例一上来就加载。

⚠️ 有一点需要大家先明确:JVM 对于类的加载是只有类 首次被使用 的时候才会被加载。但不同的单例模式实现方式会影响实例的加载时机。

1. 静态内部类实现单例模式
实现代码:
public class Singleton {
    // 私有构造函数,防止外部实例化
    private Singleton() {}

    // 静态内部类,持有 Singleton 的唯一实例
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    // 提供对外的公共方法获取单例实例
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}
特点:
  • 延迟加载:静态内部类 Holder 只有在 getInstance() 方法被首次调用时才会被加载。JVM 确保 Holder 类在首次访问其静态成员 INSTANCE 时才会被初始化,从而实现了懒加载。这样可以避免在类加载时立即创建实例,节省资源。
  • 线程安全:静态内部类的加载是由 JVM 保证线程安全的,因此静态内部类单例模式天然地实现了线程安全。
2. 饿汉式实现单例模式
实现代码:
public class Singleton {
    // 立即创建单例实例
    private static final Singleton INSTANCE = new Singleton();

    // 私有构造函数,防止外部实例化
    private Singleton() {}

    // 提供对外的公共方法获取单例实例
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
特点:
  • 饿汉式加载:在类加载时,静态成员变量 INSTANCE 被立即初始化。这意味着即使这个实例可能在类加载之后不会立即使用,它依然会在类加载时就被创建。这种方式没有延迟加载的机制,因此会在类加载时消耗资源。
  • 线程安全:由于 INSTANCE 在类加载时被初始化,类的加载过程是线程安全的,因此饿汉式单例模式天然是线程安全的。

对比分析

  1. 延迟加载
    • 静态内部类:支持延迟加载。静态内部类 Holder 只有在 getInstance() 方法首次被调用时才会被加载,这样避免了不必要的资源消耗。此处的延迟加载是因为静态内部类 Holder 的实例化是依赖于 getInstance() 方法的调用,而非类加载。
    • 饿汉式:不支持延迟加载。实例 INSTANCE 在类加载时就被创建,即使不立即使用,也会占用内存资源。这是因为在声明 INSTANCE 时就执行了 new Singleton(),导致类加载时即创建实例。
  2. 资源消耗
    • 静态内部类:只有在真正需要时才创建实例,因此更为高效,适合实例创建开销较大的情况。避免了在类加载时不必要的资源消耗。
    • 饿汉式:实例在类加载时就创建,即使没有实际使用,也会占用内存资源。这可能会导致内存消耗增加,尤其是在实例创建开销较大的情况下。
  3. 实现复杂度
    • 静态内部类:实现相对复杂,但支持延迟加载,能够有效节省资源。代码的维护和理解稍微复杂一些,但具有更好的资源管理能力。
    • 饿汉式:实现简单,但可能会导致不必要的内存消耗。其设计简单明了,但资源消耗可能会在不需要的情况下增加。
  4. 代码影响
    • 静态内部类:延迟加载是由于 Holder 类的静态成员 INSTANCE 只有在实际访问 getInstance() 方法时才会被初始化。JVM 确保 Holder 类的加载是按需进行的,这样实现了懒加载。
    • 饿汉式:实例立即加载是因为 INSTANCE 是在类加载时初始化的。private static final Singleton INSTANCE = new Singleton(); 这一行代码会在类加载时立即执行,导致实例在类加载时即创建。

总结

  • 静态内部类单例模式通过利用静态内部类的懒加载机制,实现了在实际需要时才创建实例的效果。这种方式在资源管理和延迟加载方面表现优异。
  • 饿汉式单例模式由于实例在类加载时就创建,不支持延迟加载,可能会在实例不需要时浪费资源。其实现简单,但可能导致不必要的内存消耗。

选择合适的单例模式实现方式应根据实际需求和资源情况来决定。如果需要高效的资源管理和懒加载,静态内部类实现是一个更优的选择。对于实现简单、对资源消耗不敏感的场景,饿汉式实现也是一种有效的方式。


http://www.kler.cn/a/296951.html

相关文章:

  • 数据结构绪论
  • ArcGIS小技巧:图斑变化分析
  • [SWPUCTF 2022 新生赛]
  • MySQL图形界面 --DataGrip
  • Gitlab修改已push的历史commit信息
  • Vue 3 + Element Plus 封装单列控制编辑的可编辑表格组件
  • 深度学习中常见的损失函数
  • golang学习笔记03——gin框架的核心数据结构
  • 计算机毕业设计Python+Tensorflow股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI
  • 前端框架有哪些 如何选择和优缺点
  • JVM面试真题总结(三)
  • Adobe Sensei——自动化视频编辑、特效应用和素材增强,通过AI技术快速优化视频内容,自动修复视频质量、自动添加背景音乐或字幕
  • Centos7安装FFmpeg详细步骤(已验证成功)
  • 担心违规?害怕封号?数字人直播防封技巧全解析!
  • Swift 创建扩展(Extension)
  • Java语言基础
  • [uniapp/wx小程序] 关于cover-view滚动/点击穿透问题的解决方案/cover-view 的坑
  • FreeRTOS学习笔记(四)Freertos的中断管理及临界保护
  • 浙大数据结构:04-树7 二叉搜索树的操作集
  • 【每日刷题】Day114