【设计模式 创建型】单例模式

类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)

指一个类只有一个实例,且该类能自行创建这个实例的一种模式

特点:

某个类只能有一个实例(即构造器私有,防止外部通过new XXX()创建对象

自行在类的内部创建对象实例

向外暴露一个静态的公共方法

八种单例模式实现方式:

  • 饿汉式(静态常量)

  • 饿汉式(静态代码块)

  • 懒汉式(线程不安全)

  • 懒汉式(线程安全,同步方法)

  • 懒汉式(线程安全,同步代码块)

  • 双重检查

  • 静态内部类

  • 枚举

饿汉式(静态常量)

public class Singleton {//创建实例对象private final static Singleton instance = new Singleton();/*** 构造器私有化,防止外部类能直接new*/private Singleton() {}/*** 提供一个公有的静态方法,返回实例对象* @return*/public static Singleton getInstance() {return instance;}
}

类装载的时候就完成实例化,避免了线程同步问题,如果从始至终都没有用到这个实例,则会造成内存的浪费

饿汉式(静态代码块)

public class Singleton {//实例对象private static Singleton instance;/*** 在静态代码块中,创建单例对象*/static {instance = new Singleton();}/*** 构造器私有化,防止外部类能直接new*/private Singleton() {}/*** 提供一个公有的静态方法,返回实例对象* @return*/public static Singleton getInstance() {return instance;}
}

同上

懒汉式(线程不安全)

当需要使用到对象的时候,才会创建对象即懒汉式

public class Singleton {//实例对象private static Singleton instance;/*** 构造器私有化,防止外部类能直接new*/private Singleton() {}/*** 提供一个公有的静态方法,当使用到该方法时,才会创建instance* @return*/public static Singleton getInstance() {//若对象为空,则创建if (instance == null) {instance = new Singleton();}return instance;}
}

起到了懒加载的效果,但是只能在单线程下使用,在实际开发中,不要使用这种方式

懒汉式(线程安全,同步方法)

public class YamlUtils {private static YamlUtils instance; // 类实例变量private YamlUtils() {loadConfig(); // 加载配置信息}/*** 提供一个公有的静态方法,加入同步处理,解决线程安全问题* @return*/public static synchronized YamlUtils getInstance() {if (instance == null) { // 若实例为空,则创建新实例instance = new YamlUtils();}return instance;}private void loadConfig() {}}

效率低,每个线程在想获得类的实例时候,执行 getInstance()方法都要进行同步,而其实这个方法只执行一次实例化代码就够了,后面的想获得该类的实例,直接 return 就行,方法进行同步效率太低

在实际开发中,不推荐使用

懒汉式(线程安全,同步代码块)

class Singleton {//实例对象private static Singleton instance;/*** 构造器私有化,防止外部类能直接new*/private Singleton() {}/*** 提供一个公有的静态方法* @return*/public static Singleton getInstance() {//若对象为空,则创建if (instance == null) {//同步代码块synchronized (Singleton.class) {instance = new Singleton();}}return instance;}
}

因为上面实现方式的同步方法效率太低,改为同步产生实例化的代码块

同步并不能起到线程同步的作用,假如一个线程进入了判断语句,还没有执行对象实例化,另一个线程也通过了这个判断语句,这是便会产生多个实例

实际开发中,不能使用这种方式

双重检查 🤠

public class Singleton {//实例对象private static volatile Singleton instance;/*** 构造器私有化,防止外部类能直接new*/private Singleton() {}/*** 提供一个公有的静态方法,加入双重检查处理,解决线程安全问题,* 同时解决懒加载问题,也保证了效率* @return*/public static Singleton getInstance() {//实例没创建,才会进入内部的 synchronized代码块if (instance == null) {synchronized (Singleton.class) {//此处再判断一次,可能会出现其他线程创建了实例if (instance == null) {instance = new Singleton();}}}return instance;}
}

1、DoubleCheck 概念是多线程开发中常使用到的,如代码中所示,进行了两次 if (instance == null)检查,这样就保证了线程安全。
2、实例化代码只用执行一次,后面再次访问时,判断 if (instance == null),直接 return 实例化对象,也避免反复进行方法同步。
3、线程安全,延迟加载,效率较高。
4、推荐使用这种单例设计模式。

静态内部类 🧐

public class Singleton {private Singleton() {}/*** 静态内部类,类中有一个静态属性*/private static class SingletonInstance {private static final Singleton INSTANCE = new Singleton();}public static final Singleton getInstance() {return SingletonInstance.INSTANCE ;}
}

1、这种方式采用了类装载的机制来保证初始化实例时只有一个线程。
2、静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,调用 getInstance 方法时,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化。
3、类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM 帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
4、避免了线程不安全,利用静态内部类特点实现延迟加载,效率高,推荐使用。

枚举实现单例模式

public enum Singleton{INSTANCE;public Singleton getInstance(){return INSTANCE;}
}public class SingletonTest01 {public static void main(String[] args) {Singleton instance1 = Singleton.INSTANCE.getInstance();Singleton instance2 = Singleton.INSTANCE.getInstance();System.out.println(instance1 == instance2);System.out.println("instance1=" + instance1.hashCode());System.out.println("instance2=" + instance2.hashCode());}
}

1、借助 JDK1.5 中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象

推荐使用

总结

1、单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
2、当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new。
3、单例模式使用的场景:
需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(如:数据源、session 工厂等)

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

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

相关文章

「Kafka」Broker篇

「Kafka」Broker篇 主要讲解的是在 Kafka 中是怎么存储数据的,以及 Kafka 和 Zookeeper 之间如何进行数据沟通的。 Kafka Broker 总体工作流程 Zookeeper 存储的 Kafka 信息 启动 Zookeeper 客户端: [atguiguhadoop102 zookeeper-3.5.7]$ bin/zkCli.sh通…

时间复杂度的排序

在计算机科学中,不同的算法有不同的时间复杂度。以下是一些常见的时间复杂度,并按照它们的增长速度从低到高排序: O(1) - 常数时间复杂度: 表示算法的执行时间是固定的,不随输入规模的增加而变化。例如,直接…

使用 Docker 部署 的WAF: 雷池社区版

Web应用防火墙(WAF)是保护网站不受恶意攻击的关键组件。 使用 Docker 部署雷池社区版,可以大大简化安全管理工作。 一、WAF 雷池社区版简介 雷池社区版是一种流行的开源 Web 应用防火墙,它提供基本的安全保护,如防止…

多维表格产品vika多维表、Flowus、Wolai体验记录

昨天从下午6点肝到凌晨2点多体验低代码平台多维表格产品,体验了3个国内产品,vika多维表、Flowus、Wolai。 具有多维表格新型关系数据库的鼻祖是 Airtable,国内模仿产品有vika多维表、飞书多维表格等。 还有一种类型就是以在国内鼎鼎大名的N…

细讲Labview条件结构用法及易错点

本文讲解Labview条件结构的常用情景及易错点注意事项。帮助大家深刻理解并使用该结构,欢迎点赞关注加评论,有问题可以私聊或在下方评论区留言。 本文程序均附在文章结尾,可自行下载学习。 博主之前讲过Labview事件结构、For循环等的基础知识介…

每日OJ题_算法_滑动窗口⑥_力扣438. 找到字符串中所有字母异位词

目录 力扣438. 找到字符串中所有字母异位词 解析及代码1 解析及代码2 力扣438. 找到字符串中所有字母异位词 438. 找到字符串中所有字母异位词 - 力扣(LeetCode) 难度 中等 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串&am…

Mac Could not find the GDAL library 问题解决

目录 1. 参考2. 问题描述3. 解决步骤3.1. 安装依赖包3.2. 配置 GDAL_LIBRARY_PATH3.3. 配置 GEOS_LIBRARY_PATH 1. 参考 https://docs.djangoproject.com/en/5.0/ref/contrib/gis/install/#macos 2. 问题描述 苹果系统 Mac 中搭建 GeoDjango 开发环境时出现以下报错&#xf…

第十四章 MyBatis

第十四章 MyBatis 1.入门-课程介绍2.入门-快速入门程序3.配置SQL提示4.入门-JDBC5.入门-数据库连接池6.入门-lombok工具包介绍7.基础操作-环境准备8.基础操作-删除9.基础操作-删除(预编译SQL)10.基础操作-新增11.基础操作-新增(主键返回&…

Python初识——小小爬虫

一、找到网页端url 打开浏览器,打开百度官方网页点击图片,打开百度图片 鼠标齿轮向下滑,点击宠物图片 进入宠物图片网页,在网页空白处点击鼠标右键,弹出的框中最下方显示“检查”选项,点击(我是…

安全帽识别-赋能深圳自贸中心智慧工地

在当今的建筑行业中,安全管理一直是一个至关重要的议题。深圳自贸中心项目在这方面进行了一次有益的尝试——实施智慧工地安全帽识别系统。本文将对这一创新举措进行简要介绍。 项目背景 深圳自贸中心,作为一项标志性建设项目,承载着城市发展…

云的网络安全优势

在考虑迁移到云计算时,网络安全已经成为一个关键因素。毫无疑问,企业希望通过网络浏览器或移动应用为员工、合作伙伴和客户提供一致的数据和应用访问权限,以保持竞争力。 网络攻击的性质和重要性正变得越来越复杂,并造成严重的财…

【ASP.NET Core 基础知识】--路由和请求处理--Attribute路由

一、介绍 在ASP.NET Core中,路由是将传入的URL请求映射到正确的控制器和操作的方法。Attribute路由是一种基于属性,用于定义路由规则的方式,通过在控制器类和操作方法上应用特定的属性,来定义URL模板。 基本概念: **路…

线性代数逆矩阵的求法

在线性代数中,逆矩阵是一个非常重要且有趣的概念。一个 n 阶方阵 A 的逆矩阵,记作 A^-1,是指存在另一个 n 阶方阵 B,使得 A 和 B 的乘积等于单位矩阵 E,即: A * B E 或者等价地: B * A E 这里…

uniapp技术积累

2024.01.19 1.textarea (1)默认文字样式设置 placeholder-style"color:rgba(0,0,0,0.7)" 2024.01.18 1.hbuilderx运行uniapp到ipad(复用率低) (1)电脑端:首先会有一个运行工具包&…

只用Mysql搞一个分布式锁

在web开发中,分布式的锁的应用场景甚多,我们可以通过分布式锁来进行一些仅依赖于数据库的事务很难直接保证原子性的操作,比如多种不同数据源的访问,网络通信等等。多数情况下我们会使用memcache的add, redis中在set中指定nx参数等…

怎么用小程序将身份证转为结构化Excel?

随着科技的不断发展,我们的生活变得越来越智能化。现在,我们可以使用金鸣表格文字识别小程序来识别身份证并转为结构化的excel,并且可自动核对真伪,保留头像。金鸣表格文字识别小程序是一种基于人工智能技术的应用程序&#xff0c…

nacos,nginx及java服务自重启

微服务之服务自重启 设置Nacos开机自启在/lib/systemd/system文件夹下创建nacos.service文件 [Unit] Descriptionnacos Afternetwork.target[Service] Typeforking ExecStart/opt/nacos-server-1.4.1/nacos/bin/startup.sh -m standalone ExecReload/opt/nacos-server-1.4.1/…

将字符串中的制表符替换为指定数量的空格expandtabs()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将字符串中的制表符 替换为指定数量的空格 expandtabs() [太阳]选择题 请问以下代码text3的空白处是? text1 "这里有一个\t制表符" text2 "这里有一个12345制表符…

第二次作业+第三次作业

第二次作业第三次作业 第二次作业 题目: 网站需求: ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息,教学资料和缴费网站,基于[ww…

利用HTML+CSS+JS打造炫酷时钟网页的完整指南

引言 在现代Web开发中,制作一个引人注目的时钟网页是一种常见而令人愉悦的体验。本文将介绍如何使用HTML、CSS和JavaScript来创建一个炫酷的时钟网页,通过这个项目,你将学到如何结合这三种前端技术,制作一个动态且美观的时钟效果…