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

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

相关文章:

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

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

软件测试基本知识

安全测试 安全防护策略?(漏洞扫描、入侵检查、安全日志、隔离防护) 安全日志:用于记录非法用户的登录名称、操作时间及内容等信息,以便发现问题并提出解决措施;安全日志仅记录相关信息,不对非…...

Vue项目中强制刷新页面的方法

我们在动态切换组件的过程中,导航栏和底栏不动,动态切换中间区域的情况,在首页可以进行跳转任意组件,在组件与组件之间不能相互跳转,路由发生了变化,但是页面未改变,这时我们就需要强制刷新页面…...

文件按关键字分组-切割-染色-写入excel

1. 背景 针对下面的文件data.csv,首先根据fid进行排序,然后分组,使相同fid的记录放到同一个excel文件中,并对每列重复的数据元素染上红色。 fid,user_id -1000078398032092029,230410010036537520 -1000078398032092029,23042301…...

爬虫的基本原理:爬虫概述及爬取过程

前言 随着互联网的不断发展和普及,我们的生活越来越离不开网络。而网络世界中有着海量的信息和数据,这些信息和数据对于我们的工作和生活都有很大的帮助。但是,如何高效地获取这些数据呢?这时候,爬虫这个工具就派上用…...

cocos2D插件转3D插件

cocos2D插件转3D插件 use strict;/*** 3d插件api映射,兼容2d插件* */let fs require("fs");let path require("path");let baseDir ;const prsPath (Editor.Project && Editor.Project.path ? Editor.Project.path : Editor.remote.projectP…...

[Angular] 主从表结构,从表记录在主表固定栏位上呈现

Background 主从表结构,有时为了方便数据呈现,在UI上不显示从表资料,那么需要动态把从表的资料加载到主表的固定栏位上。 例如:主表是人员信息,从表是银行卡信息,一个人在同一家银行可能有多张银行卡&…...

Kotlin Multiplatform 创建多平台分发库

目标:通过本教程学习如何使用 Kotlin Multiplatform Library 创建多平台分发库(iOS,安卓)。 创建一个项目 1、本教程使用的是Android Studio创建 2、选择 新建工程,选择 Kotlin Multiplatform Library 3、点击next 输入需要创建的项目名称以…...

[SQL挖掘机] - union/union all 使用注意事项

因为当使用union和union all操作符时,有一些注意事项需要考虑: 1. 列数和数据类型匹配: 要使用union或union all合并结果集,两个或多个查询的 select 语句必须返回相同数量和类型的列。确保每个查询返回相同的列数,并…...

php 单例模式

1&#xff0c;单例模式&#xff0c;属于创建设计模式&#xff0c;简单来说就是一个类只能有一个实例化对象&#xff0c;并提供一个当前类的全局唯一可访问入口&#xff1b; 2&#xff0c;例子 <?phpclass Singleton {private static $instance null;// 禁止被实例化priva…...

【数据结构】实验二:顺序表

实验二 顺序表 一、实验目的与要求 1&#xff09;熟悉顺序表的类型定义&#xff1b; 2&#xff09;熟悉顺序表的基本操作&#xff1b; 3&#xff09;灵活应用顺序表解决具体应用问题。 二、实验内容 1&#xff09;在一个整数序列a1,a2,…,an中&#xff0c;若存在一个数&…...

【高级数据结构】线段树

目录 最大数&#xff08;单点修改&#xff0c;区间查询&#xff09; 线段树1&#xff08;区间修改&#xff0c;区间查询&#xff09; 最大数&#xff08;单点修改&#xff0c;区间查询&#xff09; 洛谷&#xff1a;最大数https://www.luogu.com.cn/problem/P1198 题目描述 …...

qt简易闹钟

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->stopBtn->setDisabled(true);this->setFixedSize(this->size()); //设置固定大小this->s…...

python和c加加有什么区别,c和c++和python先学哪个

本篇文章给大家谈谈c加加编程和python编程有什么区别&#xff0c;以及python和c加加有什么区别&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 1、python和c学哪个好 学C好。 C通常比Python更快&#xff0c;因为C是一种编译型语言&#xff0c;而Python则是…...

Visual Studio 2022 cmake配置opencv开发环境

1. 环境与说明 这里我用的是 widnows 10 64位&#xff0c;Visual Studio 用的 Visual Studio Community 2022 (社区版) 对于Android开发工程师来说&#xff0c;为什么要使用Visual Studio 呢 ? 因为在Visual Studio中开发调试OpenCV方便&#xff0c;可以开发调试好后&#xf…...

C++ GDAL找出多时相遥感影像缺失的日期并自动生成新的全零图像作为替补

本文介绍基于C 语言的GDAL库&#xff0c;基于一个存储大量遥感影像的文件夹&#xff0c;依据每一景遥感影像的文件名中表示日期的那个字段&#xff0c;找出这些遥感影像中缺失的成像日期&#xff0c;并新生成多个像元值全部为0的栅格文件&#xff0c;作为这些缺失日期当日的遥感…...

【AI底层逻辑】——篇章5(下):机器学习算法之聚类降维时间序列

续上&#xff1a; 目录 4、聚类 5、降维 6、时间序列 三、无完美算法 往期精彩&#xff1a; 4、聚类 聚类即把相似的东西归在一起&#xff0c;与分类不同的是&#xff0c;聚类要处理的是没有标签的数据集&#xff0c;它根据样本数据的分布特性自动进行归类。 人在认知是…...

P1980 [NOIP2013 普及组] 计数问题

[NOIP2013 普及组] 计数问题 题目描述 试计算在区间 1 1 1 到 n n n 的所有整数中&#xff0c;数字 x x x&#xff08; 0 ≤ x ≤ 9 0\le x\le9 0≤x≤9&#xff09;共出现了多少次&#xff1f;例如&#xff0c;在 1 1 1 到 11 11 11 中&#xff0c;即在 1 , 2 , 3 , 4…...

需求管理全过程流程图及各阶段核心关注点详解

分析报告指出&#xff0c;多达76%的项目失败是因为差劲的需求管理&#xff0c;这个是项目失败的最主要原因&#xff0c;比落后的技术、进度失控或者混乱的变更管理还要关键。很多项目往往在开始的时候已经决定了失败&#xff0c;谜底就在谜面上&#xff0c;开始就注定的失败&am…...

Android开源 自定义emoji键盘,EmojiPack v2.1版本

目录 一&#xff0c;简介 二、安装 添加jitpack 仓库 添加依赖: 混淆规则: 三、使用 1、一次性配置emoji显示处理 二、emoji的自定义键盘的使用 一&#xff0c;简介 EmojiPack当前已提供emoji的显示和emoji的选择自定义键盘&#xff0c;在emoji显示这一方面&#xff0…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

从零开始了解数据采集(二十八)——制造业数字孪生

近年来&#xff0c;我国的工业领域正经历一场前所未有的数字化变革&#xff0c;从“双碳目标”到工业互联网平台的推广&#xff0c;国家政策和市场需求共同推动了制造业的升级。在这场变革中&#xff0c;数字孪生技术成为备受关注的关键工具&#xff0c;它不仅让企业“看见”设…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统

核心速览 研究背景 ​​研究问题​​&#xff1a;这篇文章要解决的问题是当前大型语言模型&#xff08;LLMs&#xff09;在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色&#xff0c;但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成&#xff08;RA…...

VUE3 ref 和 useTemplateRef

使用ref来绑定和获取 页面 <headerNav ref"headerNavRef"></headerNav><div click"showRef" ref"buttonRef">refbutton</div>使用ref方法const后面的命名需要跟页面的ref值一样 const buttonRef ref(buttonRef) cons…...