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 适用场景
- 实例的创建和初始化需要消耗较多时间或资源时,不希望在程序启动时就加载实例。
- 需要延迟加载实例,只有在需要的时候才创建。
- 需要在不同的线程中使用单例对象。
懒汉式可以避免在不需要实例对象时的资源浪费,只有在需要时才进行创建。这种延迟加载的特性使得它在某些情况下更加高效。
下面举一个管理文件的读写操作的例子:
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 注意事项
- 线程安全:懒汉式是线程安全的,因为通过给
getInstance()方法添加synchronized关键字,可以保证在多线程环境下只有一个线程能够进入创建实例。但是这也带来了性能上的开销。 - 性能开销:由于加了锁,每次获取实例都需要进行同步控制,可能会引起一定的性能问题。如果对性能要求较高,可以考虑使用双重检查锁定(Double-Checked Locking)等方式进行改进,以减少同步开销。
- 可序列化:如果需要将懒汉式单例对象序列化到文件或网络中,需要注意实现 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 适用场景
- 实例的创建和初始化过程较为简单,并且不会消耗过多的时间或资源。
- 希望在程序启动时就加载实例,避免在后续代码中频繁创建和初始化实例。
- 饿汉式能够保证在任何时候都能获取到实例对象,适用于简单的单例对象的创建和初始化。
下面举一个管理日志的例子:
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 注意事项
- 线程安全:饿汉式是线程安全的,因为实例对象已经在类加载时就创建好了,不存在多线程环境下的竞争问题。
- 性能与资源消耗:由于实例对象在类加载时就被创建,可能会导致一些性能和资源上的浪费,特别是在某些情况下实例对象并没有被使用到。
饿汉式是一种简单且直接的方式来创建单例对象,但也可能带来一些不必要的性能和资源消耗。因此,在实际应用中需要根据具体需求进行权衡和选择。
三、总结
懒汉式和饿汉式是两种常见的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,单例模式,属于创建设计模式,简单来说就是一个类只能有一个实例化对象,并提供一个当前类的全局唯一可访问入口; 2,例子 <?phpclass Singleton {private static $instance null;// 禁止被实例化priva…...
【数据结构】实验二:顺序表
实验二 顺序表 一、实验目的与要求 1)熟悉顺序表的类型定义; 2)熟悉顺序表的基本操作; 3)灵活应用顺序表解决具体应用问题。 二、实验内容 1)在一个整数序列a1,a2,…,an中,若存在一个数&…...
【高级数据结构】线段树
目录 最大数(单点修改,区间查询) 线段树1(区间修改,区间查询) 最大数(单点修改,区间查询) 洛谷:最大数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编程有什么区别,以及python和c加加有什么区别,希望对各位有所帮助,不要忘了收藏本站喔。 1、python和c学哪个好 学C好。 C通常比Python更快,因为C是一种编译型语言,而Python则是…...
Visual Studio 2022 cmake配置opencv开发环境
1. 环境与说明 这里我用的是 widnows 10 64位,Visual Studio 用的 Visual Studio Community 2022 (社区版) 对于Android开发工程师来说,为什么要使用Visual Studio 呢 ? 因为在Visual Studio中开发调试OpenCV方便,可以开发调试好后…...
C++ GDAL找出多时相遥感影像缺失的日期并自动生成新的全零图像作为替补
本文介绍基于C 语言的GDAL库,基于一个存储大量遥感影像的文件夹,依据每一景遥感影像的文件名中表示日期的那个字段,找出这些遥感影像中缺失的成像日期,并新生成多个像元值全部为0的栅格文件,作为这些缺失日期当日的遥感…...
【AI底层逻辑】——篇章5(下):机器学习算法之聚类降维时间序列
续上: 目录 4、聚类 5、降维 6、时间序列 三、无完美算法 往期精彩: 4、聚类 聚类即把相似的东西归在一起,与分类不同的是,聚类要处理的是没有标签的数据集,它根据样本数据的分布特性自动进行归类。 人在认知是…...
P1980 [NOIP2013 普及组] 计数问题
[NOIP2013 普及组] 计数问题 题目描述 试计算在区间 1 1 1 到 n n n 的所有整数中,数字 x x x( 0 ≤ x ≤ 9 0\le x\le9 0≤x≤9)共出现了多少次?例如,在 1 1 1 到 11 11 11 中,即在 1 , 2 , 3 , 4…...
需求管理全过程流程图及各阶段核心关注点详解
分析报告指出,多达76%的项目失败是因为差劲的需求管理,这个是项目失败的最主要原因,比落后的技术、进度失控或者混乱的变更管理还要关键。很多项目往往在开始的时候已经决定了失败,谜底就在谜面上,开始就注定的失败&am…...
Android开源 自定义emoji键盘,EmojiPack v2.1版本
目录 一,简介 二、安装 添加jitpack 仓库 添加依赖: 混淆规则: 三、使用 1、一次性配置emoji显示处理 二、emoji的自定义键盘的使用 一,简介 EmojiPack当前已提供emoji的显示和emoji的选择自定义键盘,在emoji显示这一方面࿰…...
技术速递|6000 万次 Copilot 代码审查 且仍在持续增长
作者:Ria Gopu & David Apirian排版:Alan WangCopilot 代码审查如何帮助团队跟上 AI 加速带来的代码变更。自去年 4 月我们首次推出 Copilot 代码审查(CCR)以来,其使用量已增长了 10 倍,目前已占 GitHu…...
uniapp集成腾讯地图:从marker点聚合到轨迹回放的跨端实战与性能调优
1. uniapp集成腾讯地图SDK的核心步骤 第一次在uniapp里用腾讯地图SDK时,我踩了个大坑——直接在H5端跑代码发现地图出不来。后来才明白,腾讯地图在H5端需要单独配置安全域名。具体操作是在腾讯地图开放平台申请key时,必须把H5的域名加入白名单…...
从‘腐蚀液’到‘设计美学’:PCB布线‘禁止直角’这条规则是怎么流行起来的?
从工艺限制到设计美学:PCB布线"禁止直角"规则的历史演变 在电子工程领域,PCB布线中"禁止直角"的规则几乎成为了一种行业圣经。从大学实验室到商业设计部门,新手工程师们总是被反复告诫要避免在布线中使用90度转角。但有趣…...
用Python+Simulink复现数维杯A题:手把手教你搭建车辆主动减振模型(附代码)
PythonSimulink实战:从零构建车辆主动减振系统 1. 理解车辆振动控制的核心问题 车辆振动问题一直是工程领域的重要挑战。想象一下,当你驾驶一辆重型卡车经过颠簸路面时,那种令人不适的震动不仅影响驾驶体验,长期来看还会对车辆结构…...
手把手教你用FUTURE POLICE:会议录音秒变带时间轴字幕
手把手教你用FUTURE POLICE:会议录音秒变带时间轴字幕 1. 为什么需要高精度字幕对齐? 在日常工作中,我们经常遇到这样的场景:重要会议录音需要整理成文字稿,但人工听写耗时耗力;视频剪辑时需要添加字幕&a…...
用VSCode+PlatformIO给ESP32做个简易手表:基于LVGL和1.3寸屏的UI实战
基于LVGL的ESP32智能手表开发实战:从硬件驱动到UI设计全流程 在创客圈里,ESP32凭借其出色的性价比和丰富的功能接口,一直是物联网项目的热门选择。而当我们把目光投向更直观的人机交互领域时,LVGL(Light and Versatile…...
解锁JSON Viewer 3大效率黑科技:从数据解析到开发提效的全流程解决方案
解锁JSON Viewer 3大效率黑科技:从数据解析到开发提效的全流程解决方案 【免费下载链接】json-viewer It is a Chrome extension for printing JSON and JSONP. 项目地址: https://gitcode.com/gh_mirrors/js/json-viewer JSON Viewer是一款专为开发者打造的…...
鸿蒙与Android双端蓝牙开发避坑指南:定位权限、虚拟地址与厂商SDK那些事
鸿蒙与Android双端蓝牙开发实战:权限策略与真实地址获取全解析 当你的应用需要同时在鸿蒙和Android设备上稳定运行蓝牙功能时,系统差异就像一片雷区——Android 12的权限拆分、鸿蒙4.0的虚拟地址返回、不同版本间的API兼容性,每个环节都可能让…...
ViT在语义分割中的性能优化:从VOC2012数据集看如何提升自行车识别准确率
ViT在语义分割中的性能优化:从VOC2012数据集看如何提升自行车识别准确率 语义分割作为计算机视觉领域的核心任务之一,其目标是为图像中的每个像素分配类别标签。近年来,Vision Transformer(ViT)凭借其强大的全局建模能…...
【office2pdf】PPTX 字体解析与文本样式继承(PPTX_FONT_RESOLUTION.md)
摘要 本文档记录了 PPTX 保真度问题,该问题最初看起来像是布局错误, 但实际上是由不完整的字体和文本样式解析引起的。 可见的症状是多个幻灯片上的文本块,尤其是幻灯片 4 的"SKILLS"区域, 与 PowerPoint 不匹配&#x…...
