Java设计模式之单例模式详解(懒汉式和饿汉式)

在开发工作中,有些类只需要存在一个实例,这时就可以使用单例模式。Java中的单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供全局访问点。下面来介绍一下两种常见的单例模式:懒汉式和饿汉式。

一、懒汉式

懒汉式属于一种延迟加载的单例模式,它的特点是在第一次使用时创建实例对象,而不是在类加载时就创建。

1.1 代码示例

public class LazySingleton {private static LazySingleton instance;private LazySingleton() {// 私有构造方法}public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}

在代码中,我把构造函数声明为私有的,以防止其他类直接通过构造函数创建实例对象。
getInstance() 方法是获取实例对象的入口。在该方法内部,首先检查实例对象 instance是否已经被创建。如果实例对象为 null,表示还没有创建过,就通过调用构造函数来创建实例对象。如果已经创建过,就直接返回已有的实例对象。

为了保证线程安全,在 getInstance() 方法上添加了 synchronized 关键字,使得在多线程环境下只有一个线程能够进入创建实例。保证了多线程情况下只会创建一个实例对象。

1.2 适用场景

  1. 实例的创建和初始化需要消耗较多时间或资源时,不希望在程序启动时就加载实例。
  2. 需要延迟加载实例,只有在需要的时候才创建。
  3. 需要在不同的线程中使用单例对象。

懒汉式可以避免在不需要实例对象时的资源浪费,只有在需要时才进行创建。这种延迟加载的特性使得它在某些情况下更加高效。

下面举一个管理文件的读写操作的例子:

public class FileManager {private static FileManager instance;private File file;private FileManager() {// 初始化文件对象file = new File("D:\\file\\demo.txt");}public static synchronized FileManager getInstance() {if (instance == null) {instance = new FileManager();}return instance;}public void readFile() {// 读取文件内容并进行相应操作...}}

在上述示例中,通过懒汉式单例模式,我们可以确保在第一次调用 getInstance() 方法时才创建实例对象。其他类可以通过调用该方法获取 FileManager 的实例对象。然后,可以使用该实例对象的方法来进行文件操作,例如 readFile() 方法。这样,无论在哪个地方需要读写文件,都可以通过 FileManager.getInstance().readFile() 方法来使用文件管理器。

总的来说,懒汉式适用于在第一次使用时才进行对象创建的场景,并且在实例对象初始化过程中没有复杂的线程安全要求。文件管理器就是一个典型的例子,因为在应用程序启动时可能不需要立即读写文件,而是在需要的时候才进行相关操作。

1.3 注意事项

  1. 线程安全:懒汉式是线程安全的,因为通过给 getInstance() 方法添加 synchronized 关键字,可以保证在多线程环境下只有一个线程能够进入创建实例。但是这也带来了性能上的开销。
  2. 性能开销:由于加了锁,每次获取实例都需要进行同步控制,可能会引起一定的性能问题。如果对性能要求较高,可以考虑使用双重检查锁定(Double-Checked Locking)等方式进行改进,以减少同步开销。
  3. 可序列化:如果需要将懒汉式单例对象序列化到文件或网络中,需要注意实现 Serializable 接口,以确保对象的序列化和反序列化过程正确无误。

二、饿汉式

饿汉式是一种在类加载时就创建实例的单例模式。它的特点是无论是否会被使用到,实例对象都在类加载时被创建。

2.1 示例代码

public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton();private EagerSingleton() {// 私有构造方法}public static EagerSingleton getInstance() {return instance;}
}

在代码中,先把实例对象 instance 定义为静态的 final 变量,并在声明时就进行实例化。

因为实例对象在类加载时就被创建,所以可以保证在任何情况下都能获取到同一个实例对象。

2.2 适用场景

  1. 实例的创建和初始化过程较为简单,并且不会消耗过多的时间或资源。
  2. 希望在程序启动时就加载实例,避免在后续代码中频繁创建和初始化实例。
  3. 饿汉式能够保证在任何时候都能获取到实例对象,适用于简单的单例对象的创建和初始化。

下面举一个管理日志的例子:

public class Logger {private static final Logger instance = new Logger();private Logger() {// 初始化日志记录器}public static Logger getInstance() {return instance;}public void log(String message) {// 记录日志消息}// 其他日志操作方法...
}

上述示例中,在 Logger 类的内部,将实例对象 instance 定义为静态的 final 变量,并在声明时就进行实例化。这样,在类加载时实例对象就会被创建。然后通过提供 getInstance() 方法,其他类可以调用该方法获取 Logger 的实例对象。然后,可以使用该实例对象的方法来记录日志消息,例如 log(String message) 方法。

这样,无论在哪个地方需要记录日志,都可以通过 Logger.getInstance().log(String message) 方法来使用日志记录器。

总的来说,饿汉式适用于需要在程序启动时就初始化的资源,且在整个应用程序的生命周期中都需要使用到的场景。日志记录器就比较适合,因为日志记录功能通常需要在应用程序启动之初就准备好,并在整个应用程序的运行过程中记录日志消息。

2.3 注意事项

  1. 线程安全:饿汉式是线程安全的,因为实例对象已经在类加载时就创建好了,不存在多线程环境下的竞争问题。
  2. 性能与资源消耗:由于实例对象在类加载时就被创建,可能会导致一些性能和资源上的浪费,特别是在某些情况下实例对象并没有被使用到。

饿汉式是一种简单且直接的方式来创建单例对象,但也可能带来一些不必要的性能和资源消耗。因此,在实际应用中需要根据具体需求进行权衡和选择。

三、总结

懒汉式和饿汉式是两种常见的Java单例模式。懒汉式在第一次使用时创建实例,而饿汉式在类加载时就创建实例。需要注意的是,在实际应用中,应根据具体场景进行综合考虑和设计。选择合适的单例模式可以提高代码的可维护性和性能 ~

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

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

相关文章

Vue项目如何生成树形目录结构

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、有兴趣的可以关注一手。 前言 项目的目录结构清晰、可以帮助我们更快理顺项目的整体构成。在写文档之类的时候也比较方便。生成树形目录的方式有多种,我这里简单介绍其中一种较为简单的实现 过…

学习数学助手Schooltech Math Resource Studio 7.0 Crack

数学资源工作室 数学工作表生成器:快速轻松地创建数学工作表 使用易于使用的数学工作表生成器软件创建可打印的数学练习工作表。通过练习、谜题、问题等提高数学技能。 瞄准学习需求并激励学生 Math Resource Studio 是个性化数学教学的理想软件解决方案&#xff0c…

什么是商业大数据?——邓承聪

在数聚股份看来,企业已经身处商务大数据时代。 每一次工业(科技)革命,都有其标志产物。从一开始的蒸汽机、内燃机、电信技术,到七八十年代崛起的互联网技术。如今,在新一轮科技革命的浪潮之中,则…

【SDOF振荡器的非线性-非弹性多轴时间响应分析】用于SDOF振荡器非线性非弹性时程分析的鲁棒性分析研究(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码实现 💥1 概述 进行SDOF振荡器的非线性非弹性时程分析的鲁棒性分析研究,旨在探究该方法对不同系统参数和分析条件变化的稳定性和可靠性。以下是一…

springboot拦截器

简述sprinboot拦截器使用. 定义一个拦截器处理类 简单来说就是你将访问拦截下来要干什么 比如验证身份或者 登录状态,权限等 实在只想看一下拦截效果,不想实现其他功能就直接写一个控制台输出也行 示例: public class AppIdInterceptor implements HandlerInterceptor { pri…

几百本常用计算机开发语言电子书链接

GitHub - XiangLinPro/IT_book: 本项目收藏这些年来看过或者听过的一些不错的常用的上千本书籍,没准你想找的书就在这里呢,包含了互联网行业大多数书籍和面试经验题目等等。有人工智能系列(常用深度学习框架TensorFlow、pytorch、keras。NLP、…

用HTML写一个简单的静态购物网站

实现代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>购物网站</title> &l…

FRR+VPP

安装 三者的结合&#xff0c;实际上编译安装好就行了&#xff0c;不需要做任何代码上的修改&#xff0c;只需要安装和配置&#xff0c;然后你就有了一台路由器。 FRRouting使用frr-8.5.2版本&#xff0c;VPP使用23.06版本&#xff0c;DPDK和lcpng是VPP的插件&#xff0c;安装…

DataEase开源BI工具安装_数据全量_增量同步_大屏拖拽自动生成_多数据源支持_数据血缘分析---大数据工作笔记0183

我这里用的是Centos7.9安装的 可以通过uname -p来查看一下我们的电脑架构,可以看到是x86_64架构的 我们下第一个,这个是x86架构的,第二个arm架构的 然后解压到/opt/module中 然后再去重命名一下文件夹. 推荐200G 本地模式的功能比较多 推荐100G

umy-ui树形结构表格懒加载用法详解

效果图 在做后台时&#xff0c;使用的iview组件库中的树形表格&#xff0c;但数据量过大时会导致页面卡死&#xff0c;借助umy-ui的虚拟表格完美解决了数据量大卡顿的问题。 先放文档&#xff1a;http://www.umyui.com/umycomponent/u-table-column-api 安装 npm install u…

apifox 调用camunda engine-rest接口报错“type“: “NotFoundException“

官方文档在这&#xff1a; https://docs.camunda.org/rest/camunda-bpm-platform/7.19/ 现象 engine-rest本是可以直接请求的&#xff0c;我把openapi导入到apifox之中了&#xff0c;我测试一下接口没有能请求成功的&#xff0c;基本都报以下的错。 报错如下 {"type&qu…

Flutter:flutter_local_notifications——消息推送的学习

前言 注&#xff1a; 刚开始学习&#xff0c;如果某些案例使用时遇到问题&#xff0c;可以自行百度、查看官方案例、官方github。 简介 Flutter Local Notifications是一个用于在Flutter应用程序中显示本地通知的插件。它提供了一个简单而强大的方法来在设备上发送通知&#…

【MTK平台】【wpa_supplicant】关于wpa_supplicant_8/src/p2p/p2p.c文件的介绍

本文主要介绍external/wpa_supplicant_8/src/p2p/p2p.c文件 先看下p2p_find 这个方法 P2P_find 主要用于 P2P&#xff08;点对点&#xff09;网络中查找其他对等方的功能。另外可以看到设置P2P模块的状态为 P2P_SEARCH int p2p_find(struct p2p_data *p2p, unsigned int tim…

【LeetCode-简单】剑指 Offer 24. 反转链表(详解)

题目 定义一个函数&#xff0c;输入一个链表的头节点&#xff0c;反转该链表并输出反转后链表的头节点。 方法&#xff1a;迭代 思路 定义三个指针&#xff0c;一起往后走&#xff0c;走一步就修改mid指针的next&#xff0c;原本是mid的next 是right&#xff0c;我们修改成l…

安装支持vs2019的MFC(解决MSBuild 错误 MSB8041、MSB8042)

安装支持MFC的vs2019&#xff08;解决MSBuild 错误 MSB8041、MSB8042&#xff09; 常用安装选项解决MSBuild 错误 常用安装选项 解决MSBuild 错误 安装上述勾选内容后&#xff0c;即可解决MSBuild 错误 MSB8041 MSB8041&#xff1a;此项目需要 MFC/ATL 库。 https://learn.mic…

Easy-Es笔记

一、Easy-ES概述 Easy-Es&#xff08;简称EE&#xff09;是一款由国内开发者打造并完全开源的ElasticSearch-ORM框架。在原生 RestHighLevelClient 的基础上&#xff0c;只做增强不做改变&#xff0c;为简化开发、提高效率而生。Easy-Es采用和MP一致的语法设计&#xff0c;降低…

STM32CubeMX配置STM32G031多通道ADC采集(HAL库开发)

时钟配置HSI主频配置64M 勾选打开8个通道的ADC 使能连续转换模式 配置好串口&#xff0c;选择异步模式配置好需要的开发环境并获取代码 修改main.c 串口重定向 #include "stdio.h" int fputc(int ch, FILE *f) {HAL_UART_Transmit(&huart1, (uint8_t *)&ch…

Verilog | Round_Robin_Arbiter

重写了权重轮询仲裁&#xff0c;添加lock输入信号&#xff0c;表示请求方收到了仲裁许可&#xff0c;在对应的lock拉低之前&#xff0c;仲裁器不可以开启新的仲裁。 Generics Generic nameTypeValueDescriptionN4 Ports Port nameDirectionTypeDescriptionclkinputrst_ninp…

运维工程师第一阶段windows的学习

文章目录 计算机硬件组成计算机历史计算机硬件组成最重要的三个硬件冯诺依曼体系:组装一台电脑:虚拟机和装系统虚拟机VMware安装系统搭建局域网本地安全策略用户本地安全策略共享文件删除操作系统操作系统分类系统优化常用命令系统的启动和密码破解winodws启动过程windows系统…

牛客上面的约瑟夫环问题

对于本题 我感觉还是链表做起来舒服 数组也可以做 但是数组需要去控制循环 不太好控制 我之前搞了 最后看别人的实现 但是链表搞了一次就搞好了 香的嘞~ 下面是代码 用单链表实现循环 再去删除要删除的人 5个人 数到2 你们在纸上画图 我就不画了 对于数组实现你们可以去…