Java设计模式之单例模式(Singleton)模式

单例模式(Singleton)确保一个类只有一个实例,且提供一个全局访问点。

什么是单例模式

单例模式是一种非常常用的设计模式,它可以确保一个类只有一个实例,并且提供一个全局访问点。在单例模式中,应用程序中的所有代码都可以访问到该实例对象,从而可以确保该对象的状态和行为都是一致的。单例模式通常使用静态变量去存储该类的唯一实例,同时将构造函数的访问限制为私有,这样就可以防止其他代码创建该类的实例。

单例模式的使用场景

  1. 当需要确保一个类只有一个实例,并且全局代码都可以访问该实例时,可以使用单例模式。例如,数据库连接池、线程池、配置文件等都可以使用单例模式来确保系统中只有一个实例。

  2. 当需要对实例进行严格控制并限制其访问时,可以使用单例模式。例如,操作系统中的文件系统和窗口管理器都是使用单例模式来确保只有一个实例,以便进行统一的管理和调度。

单例模式的代码示例

Java 的单例模式实现有以下几种方式:

  1. 饿汉式单例模式:
public class Singleton {// 类初始化时即创建实例private static final Singleton INSTANCE = new Singleton();// 构造函数私有化,禁止外部实例化private Singleton() {}public static Singleton getInstance() {return INSTANCE;}
}

该方式的缺点是当应用启动时就创建对象,可能会占用资源,甚至出现“灾难性”后果。不过由于其线程安全,简单易懂等特点,在一些极简单的场景中,还是能够使用。

  1. 懒汉式单例模式:
public class Singleton {// 加上 volatile,防止多线程环境下,由于指令重排导致的 INSTANCE 状态异常private static volatile Singleton INSTANCE;private Singleton() {}public static Singleton getInstance() {if (INSTANCE == null) {synchronized (Singleton.class) {if (INSTANCE == null) {INSTANCE = new Singleton();}}}return INSTANCE;}
}

该方式延迟了单例对象的实例化,但是需要注意多线程环境下的线程安全问题,需要通过加锁来解决。如果没有加锁,就会出现多线程并发时,创建多个实例的情况。

  1. 静态内部类单例模式:
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

该方式通过静态内部类来实现懒汉式单例模式,既实现了懒加载,又实现了线程安全,并且也不会出现指令重排等问题。

  1. 枚举单例模式
public enum Singleton {INSTANCE;public void doSomething() {// do something}
}

枚举单例模式是一种非常优雅的单例模式实现,可以保证线程安全,处理序列化等问题。此时,实例就是一个枚举值,每个枚举值都是一个全局唯一的实例。
当然可以,以下是对上面教程的补充和完善:

  1. 双重检查锁定单例模式
public class Singleton {private static volatile Singleton INSTANCE;private Singleton() {}public static Singleton getInstance() {if (INSTANCE == null) {synchronized (Singleton.class) {if (INSTANCE == null) {INSTANCE = new Singleton();}}}return INSTANCE;}
}

该方式实现了线程安全,而且在实例创建之前,只对某个线程加锁了一次,避免了多次加锁的性能损失。但需要注意的是,新手难以理解和使用该方式,因此建议采用内部静态类方式实现单例模式。

  1. 内部静态类单例模式
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

该方式在实现原理上和懒汉式非常类似,但是将实例化对象的过程放到了一个私有的内部静态类中,在 Singleton 类加载的时候并不会对 SingletonHolder 进行初始化,只有在第一次调用 getInstance() 方法时,才会导致 SingletonHolder 类被加载,这样才实例化 instance。

单例模式的实际应用

下面是几个常用的框架及其使用单例模式的例子:

  1. Spring 框架

Spring 框架是一种轻量级的 Java 开发框架,广泛应用于企业级应用开发中。在 Spring 框架中,许多组件都使用了单例模式。例如:

  • BeanFactory:一个全局的 IoC 容器,其中存储了系统中所有的 Bean 实例。
  • ApplicationContext:一个基于 BeanFactory 的上层接口,提供了更多高级的特性,合适于大多数应用。
  • ResourceLoader:用于加载各种资源文件(如配置文件、XML 文件等)的工具类。
  • ServletContext:一个全局的 Servlet 上下文,存储了与当前 Web 应用相关的各种信息和资源。

这些组件都使用了单例模式,以确保系统中只有一个实例,并且全局可以访问到该实例。

  1. Log4j 框架

Log4j 是一种常用的 Java 日志框架,可以帮助开发者对系统进行日志记录。在 Log4j 框架中,Logger 类是一个单例类,它负责接收系统产生的日志信息,并将其输出到文件、数据库等目的地。Log4j 框架设计为单例模式,可确保系统中只有一个 Logger 实例,并且可以全局访问到该实例。

  1. Hibernate 框架

Hibernate 是一种常用的 Java 数据库映射框架,可以帮助开发者将 Java 对象映射到关系型数据库中。在 Hibernate 框架中,SessionFactory 类是一个单例类,它负责管理所有的 Hibernate Session 实例。SessionFactory 类使用单例模式,可以确保系统中只有一个实例,并且全局可以访问到该实例。

  1. Java 连接池

Java 连接池是一种常用的数据库连接管理工具,可以帮助开发者实现数据库连接的共享和复用。在 Java 连接池中,使用了单例模式来确保数据库连接池对象只有一个实例,并且可以全局访问。例如,Tomcat 容器中的 JDBC 数据库连接池就是使用单例模式实现的。

关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员👩‍💻👨‍💻!

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

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

相关文章

java(springboot)对接elasticsearch8+

1、pom引用 注&#xff1a;jackson包es只用到了databind&#xff0c;之所以全部引用是因为actuator用到了其他&#xff0c;只升级一个会 导致版本冲突 <!-- https://mvnrepository.com/artifact/co.elastic.clients/elasticsearch-java --> <dependency><grou…

七大排序算法和计数排序

文章目录 一、直接插入排序二、希尔排序三、直接选择排序四、堆排序五、冒泡排序六、快速排序6.1递归实现快速排序6.2非递归实现快速排序 七、归并排序7.1递归实现归并排序7.2非递归实现归并排序 八、计数排序 以下排序以从小到大排序为例 一、直接插入排序 时间复杂度&#x…

文章审核之敏感词过滤

技术选型 DFA实现原理 DFA全称为&#xff1a;Deterministic Finite Automaton,即确定有穷自动机。 存储&#xff1a;一次性的把所有的敏感词存储到了多个map中&#xff0c;就是下图表示这种结构 敏感词&#xff1a;冰毒、大麻、大坏蛋 工具类 最下面的main方法是测试用的&a…

Java版本电子招标采购系统源代码—企业战略布局下的采购寻源

智慧寻源 多策略、多场景寻源&#xff0c;多种看板让寻源过程全程可监控&#xff0c;根据不同采购场景&#xff0c;采取不同寻源策略&#xff0c; 实现采购寻源线上化管控&#xff1b;同时支持公域和私域寻源。 询价比价 全程线上询比价&#xff0c;信息公开透明&#xff0c;可…

微信小程序-地图上的图标计算旋转值朝向经纬度计算

废话不多说&#xff0c;开整 // 参数为寄件人经纬度和收件人经纬度 // 根据寄收件人经纬度弧度π进行rotate旋转计算 const getRotate (po1, po2) > {if (!(po1 && po2)) return 0const lng_a po1.longitudeconst lat_a po1.latitudeconst lng_b po2.longitud…

MySQL使用

目录 1 MySQL的登录 1.1 服务的启动和终止 1.2 自带客户端的登录与退出 2 MySQL演示使用 2.1 MySQL的使用演示 2.2 MySQL的编码设置 1 MySQL的登录 1.1 服务的启动和终止 MySQL安装完毕以后&#xff0c;需要启动服务器进程&#xff0c;不然客户端无法连接数据库。 在前面…

vue-cli项目中,使用webpack-bundle-analyzer进行模块分析,查看各个模块的体积,方便后期代码优化

一、安装 npm install --save-dev webpack-bundle-analyzer 二、在vue.config.js中配置 const BundleAnalyzerPlugin require(webpack-bundle-analyzer).BundleAnalyzerPlugin plugins: [new BundleAnalyzerPlugin({analyzerMode: server,analyzerHost: 127.0.0.1,analyze…

Word2Vec实现文本识别分类

深度学习训练营之使用Word2Vec实现文本识别分类 原文链接环境介绍前言前置工作设置GPU数据查看构建数据迭代器 Word2Vec的调用生成数据批次和迭代器模型训练初始化拆分数据集并进行训练 预测 原文链接 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&…

探析国内数字孪生引擎技术现状

在数字孪生软件来发中&#xff0c;渲染引擎是一个关键点&#xff0c;国内大多数字孪生平台引擎通常使用的是自研的渲染引擎或者采用开源的渲染引擎。下面通过一些常见的渲染引擎在国内数字孪生引擎中的应用带大家了解数字孪生软件开发的方式。 自研渲染引擎&#xff1a;许多数…

HTTPS安全套接字层超文本传输协议

HTTPS安全套接字层超文本传输协议 HTTPS简介HTTPS和HTTP的主要区别客户端在使用HTTPS方式与Web服务器通信时的步骤SSL/TLS协议的加密&#xff08;握手&#xff09;过程为什么数据传输阶段使用对称加密HTTPS 的优点HTTPS 的缺点HTTPS 的优化证书优化会话复用 HTTPS简介 HTTP协议…

文件包含漏洞利用思路

简介 通过PHP函数引入文件时&#xff0c;传入的文件名没有经过合理的验证&#xff0c;从而操作了预想之外的文件&#xff0c;导致意外的文件泄漏甚至恶意代码注入。 常见的文件包含函数 php中常见的文件包含函数有以下四种&#xff1a; include()require()include_once()re…

海外服务器推荐:国外高性能服务器免费

对于寻找高性能的海外服务器&#xff0c;海外服务器推荐指导&#xff0c;我建议您考虑以下因素&#xff1a; 1. 可靠性和性能&#xff1a;选择信誉良好、可靠性好的服务器提供商。它们应该有稳定的网络基础设施和高性能的服务器硬件来满足您的需求。 2. 位置选择&#xff1a;…

苍穹外卖day05——Redis(被病毒入侵)+店铺营业状态设置

Redis被病毒入侵了 数据删光光然后只剩这四个玩意&#xff0c;乱下东西乱删东西&#xff0c;还好是docker部署&#xff0c;不然就寄了。 在服务器上部署redis记得一定要设置密码&#xff0c;不然被人扫肉鸡注入病毒整个服务器给你崩掉。 使用配置类的方式搭建相关程序 配置数…

医生出国访问交流,为什么要趁早申请访问学者?

在当前国内&#xff0c;有这样一类医生群体&#xff0c;他们四十岁上下&#xff0c;就职于国内大型三甲医院&#xff0c;受过良好教育&#xff0c;事业辉煌&#xff0c;属于是别人眼中的精英阶层&#xff0c;然而&#xff0c;随着岁月的沉淀&#xff0c;副高级别医生群体的人生…

实现简单Spring基于XML的配置程序

定义一个容器&#xff0c;使用ConcurrentHashMap 做为单例对象的容器 先解析beans.xml得到第一个bean对象的信息&#xff0c;id&#xff0c;class&#xff0c;属性和属性值使用反射生成对象&#xff0c;并赋值将创建好的bean对象放入到singletonObjects集合中提供getBean(id)方…

Java实现根据商品ID获取1688商品详情数据方法

要通过1688的API获取商品详情数据&#xff0c;您可以使用1688开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过1688开放平台API获取商品详情&#xff1a; 首先&#xff0c;确保您已注册成为1688开放平台的开发者&#xff0c;并创建一…

【Redis】剖析RDB和AOF持久化原理

文章目录 前言1、AOF日志1.1、概述1.2、日志文件1.3、写回策略1.4、策略实现原理1.5、重写机制1.6、AOF 后台重写1.6.1、介绍1.6.2、实现原理 1.7、优缺点 2、RDB快照2.1、概述2.2、实现方式2.3、实现原理2.4、极端情况2.5、优缺点 3、混合体实现4、大Key问题4.1、何为大key4.2…

profinet 调试记录

一、 树莓派运行codesys runtime 1. 用户名称要以 root 登录 若是普通用户&#xff0c;会提示&#xff1a;脚本必须以 root 身份运行 2. codesys报错&#xff1a; 在树莓派config.txt文件添加&#xff1a;arm_64bit0 3. 扫描设备需开启PLC 图标变红&#xff0c;则开启成…

【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比

【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比 一、数据介绍 基于UCI葡萄酒数据集进行葡萄酒分类及产地预测 共包含178组样本数据&#xff0c;来源于三个葡萄酒产地&#xff0c;每组数据包含产地标签及13种化学元素含量&#xff0c;即已知类…

Python组合模式介绍、使用方法

一、Python组合模式介绍 概念&#xff1a; 组合模式(Composite Pattern)是一种结构型设计模式&#xff0c;它通过将对象组合成树状结构来表示“整体/部分”层次结构&#xff0c;让客户端可以以相同的方式处理单个对象和组合对象。 功能&#xff1a; 统一对待组合对象和叶子对…