[DP]Singleton设计模式

C#串口通信从入门到精通(21)——一个串口多线程发送数据 本文详细介绍了串口通信中采用多线程发送串口数据的解决方案,由多年实战经验总结,绝对干货! 阅读详情

单例模式:单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类有且只有一个实例。

单例模式最初的定义出现于《设计模式》:“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”

一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

单例模式的特点:

1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。



首先我们从一个简单的单例模式(饿汉式)开始构建:

饿汉式:

class USBDriver {
	private static USBDriver driver = new USBDriver();

	private USBDriver() {
	}

	public static USBDriver getInstance() {
		return driver;
	}
}

首先什么是饿汉式呢,我们都知道一个饿汉肯定是对事物渴求,也就是对某种资源渴求的。所以我们的饿汉单例模式 也就是对 单例十分的渴求

渴求到什么程度呢,当类装载进来的时候 就立即着手构建我们的实例了。这里private的构造函数,是防治new出来,这样就不是单例了。

这里需要问一个问题,这会不会引起线程安全问题?

答案是不会,因为在USBDriver类初始化时,就已经加载进来了,所以在调用getInstance()时候,并不会产生线程安全问题,可以说天生就是线程安全的。



如果我们的驱动程序比较耗费资源,如果我们可能会用到几十种甚至更多的驱动程序的话,那么我们对于这种饿汉单例模式是不是需要进行一些改进,

使的当我们真正需要该实例的时候才初始化,那么我们什么时候才真正需要该实例呢?就是我们调用getInstance()的时候。

class USBDriver {
	private static USBDriver driver = null;

	private USBDriver() {
	}

	public static synchronized USBDriver getInstance() {
		if (driver == null) {
			driver = new USBDriver();
		}
		return driver;
	}
}

好的,这次我们再一次改进,对于该单例我们采取了懒加载策略(懒汉式),直到需要用的时候才构建。

这里我们给整个getInstance()方法使用了synchronized 来锁定该方法。

这样同样带一个问题,就是因为锁的粒度是方法级的,所以对于多于多线程性能会产生很大的问题。

所以我们可以将锁适当的细化,将锁移至内部,采用更小的锁块来进行优化(双重检查锁定式)。

class USBDriver {
	private static volatile USBDriver driver = null;

	private USBDriver() {
	}

	public static USBDriver getInstance() {
		if (driver == null) {
			synchronized (USBDriver.class) {
				if (driver == null) {
					driver = new USBDriver();
				}
			}
		}
		return driver;
	}
}

这里我们在driver 里面加了 volatile 修饰,这是为了保证读和取都是在保证不会被多线程打断,这是一种保护措施,保证获得driver 的最新信息。

为什么要采用双重检查策略呢?考虑一种情况,当我一个线程执行到 if(driver ==null)的时候,这个时候driver还没初始化,如果不采用双重检查的话,我读到了driver =null,但是这个时候有一个线程抢险进行到了同步代码块。

当driver 构建之后,之前的线程因为读到了 driver = null,实际上这个时候driver 并不是null了

这就无异带来了线程安全问题,而且更糟糕的是,可能会产生引用逸出。

即 我一个线程先 调用getInstance获得了一个driver,然后后一个线程产生上述分析的情况,重新new 了一个driver。这个时候就破坏了有且只有一个的特性。


事实上,这种双重检查锁定策略,在ConcurrentHashMap也是有类似的设计的。


那么有没有办法避免同步代码块呢?

是可以的,不过这利用到jvm保证每个类只被加载一次的特性。

在我们的驱动类内增加一个内部内,该内部类持有驱动实例,但是该实例,只有在该类被加载的时候才会真正的初始化。

class USBDriver {
	private USBDriver() {
	}

	private static class USBDriverHolder {
		private static USBDriver driver = new USBDriver();
	}

	public static USBDriver getInstance() {
		return USBDriverHolder.driver;
	}
}

这种方式称为静态内部类单例,该方法无疑在简洁性,性能上都有很大的优势,但是有个弊端,就是必须对驱动类进行大的结构变动。很多情况下,我们无法改动代码内部源码,

比如引入外部的jar。




看看spring中的单例:

DefaultSingletonBeanRegistry类中的getSingleton方法

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}


我们可以看到spring中对于单例似乎是用了我们的懒加载的 双重检查锁定。

这里spring 采取双重检查锁定也是有一定原因的。如果使用懒汉式势必带来运行效率的降低,

如果采用静态内部类单例,必须去改动源码。spring 并不会侵入你的代码。








2026华为OD面试题029:勇攀数字高峰 在给定的数字地形图里寻找登山路径,数字代表当前位置的海拔高度。要求从最低海拔出发,不断攀登,最终到达最高山峰。地图保证最低海拔和最高山峰都只有一个。 登山规则: - 路径上的海拔必须严格递增 - 只能向上下左右 4 个方向移动 - 路径必须从最低海拔开始,到最高海拔结束 - 每个地点只能走一次 - 每一步的攀登高度差必须大于 0,且不超过指定值 `K` 输出满足条件的登山路径的数量。 阅读详情

相关推荐

【阿里云大模型高级工程师ACP学习笔记】2.8 部署模型

【摘要】本文主要分享自学阿里云大模型高级工程师 ACP 认证中《2.8 部署模型》的学习笔记。详细介绍学习目标、梳理涵盖的知识点并评估其重要性和难易度,对既重要又困难的知识点进行重点分析,旨在为对阿里云大模型学习和认证感兴趣的读者提供学习思路和经验参考。

davidkorhenn的博客 2060

Spring获取单例getSingleton(1)

标签: spring源码学习 spring获取单例首先是从缓存去找,如果找不到就要从头开始bean的加载过程,spring中主要通过getSingleton的重载方法实现单例bean的加载过程 要创建一个bean的单例,首先了解下单例是什么样子的, public static synchronized Singleton...

weixin_34221112的博客 576

别急着编译!修复银河麒麟OpenSSH漏洞前,先搞懂ssh、sshd版本与apt仓库的“爱恨情仇”

本文深度解析银河麒麟OpenSSH漏洞(CVE-2023-38408)修复策略,揭示版本差异背后的企业级维护逻辑,提供从APT升级到源码编译的多维度方案评估。特别针对路径隔离方案和离线环境处理给出技术细节,帮助企业制定兼顾安全与稳定的升级决策框架。

weixin_26642481的博客 453

设计模式之单例模式及其应用

一、 单例模式概述 Java中单例模式的定义是:一个类只有一个实例,而且自行实例化并且向整个系统提供这个实例。 优点:由于单例模式在内存中只有一个实例,减少了内存开支和系统的性能开销;单例模式可以避免对资源的多重占用。   二、单例模式的几种形式 1.  饿汉式单例 public class Singleton { private static final Singleton sin

挚爱左岸 504

Open3D——RANSAC 三维点云空间直线拟合【2025最新版】

使用RANSAC算法在点云数据中拟合三维空间直线的python代码实现。博客长期更新,本文最新更新时间为:2025年3月23日。

点云侠的博客 7354

K8S搭建(centos)四、安装K8S

每个人都有惰性,但不断学习是好好生活的根本,共勉!

感谢阅读 2644

设计模式 (六)单例模式(Singleton)

单例模式就是确保一个类只有一个实例,并且该实例必须自动创建,并向整个系统提供该实例。这样保证了对外的对象的属性等均为一个实例,就像是银行取款 单例模式原理图: 单例模式分为饿汉式单例模式和懒汉式单例模式。 饿汉式单例模式代码 package com.designpattern.singleton; public class HungrySingleton { private H...

数据库天地 146

2025.06.06【Ribo-seq】|riboWaltz:P-site定位与三碱基周期性分析流程

同学们,大家好!今天我们要学习的是riboWaltz——一款专为Ribo-seq(核糖体足迹测序)数据设计的R包,主要用于P-site定位优化和三碱基周期性分析。P-site的准确定位是Ribo-seq下游所有翻译组学分析的基础,riboWaltz为我们提供了系统、可视化、易用的解决方案。P-site定位优化:自动识别不同长度RPF的最佳P-site偏移量。三碱基周期性分析:可视化RPF在CDS、UTR等区域的分布,评估数据质量。多样本/多条件支持:可同时处理多个样本,便于批量分析和对比。

1790

单例(Singleton)设计模式

单例(Singleton)设计模式 设计模式:解决某一类问题行之有效的解决办法 一、单例设计模式解决的问题### 可以保证一个类对象的唯一性场景:多个程序要使用一个配置文件中的数据,并且要实现数据共享和交换。那么,必须要将多个数据封装到一个对象中。多个程序同时操作同一个对象。二、实现过程怎样能保证对象的唯一性1.一个类要是提供了构造函数,就可能产生多个对象,所以不要让其他程序建立对象。2.仅仅在

jld2700zx的博客 740

YOLOv8交通监控全方案:精准车辆计数+违章(闯红灯/压线)识别,拿来就落地!

作为深耕计算机视觉落地的开发者,我见过太多交通监控的“伪智能”——传统系统要么车辆计数不准(漏计/重复计数),要么违章识别滞后(靠人工回看录像),甚至连“闯红灯、压线”这类常见违章都无法实时判定,完全满足不了实际交通管理需求。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 646

数据分片的三种方式:哈希、一致性哈希、按照数据范围分片

数据分片就是按照一定的规则,将数据集划分成相互独立、正交的数据子集,然后将数据子集分布到不同的节点上。通过设计合理的数据分片规则,可将系统中的数据分布在不同的物理数据库中,达到提升应用系统数据处理速度的目的。三种常用的数据分片方式:1. 哈希分片2. 一致性哈希分片(Consistent Hash)3. 按照数据范围分片(Range Based)数据分片的应用场景:1. 数据库扩展2. 分布式缓存对集群部署多个缓存节点,提高缓存的处理能力。

wjianwei666的专栏 1133

设计模式-01单例模式 Singleton

单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。 比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象。SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,这是就会使用到单例模式 单例模式有八种方式: 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安

XiXavier的博客 265

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

设计模式之单例模式 Singleton

package org.example.dp; public class Singleton { private static class LazySingleton { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return LazySingleton.INSTANCE; } }

faceqq的博客 140

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

设计模式——单例模式(Singleton)

文章目录1. 单例模式1.1 定义1.2 单例模式结构图1.3 分类1.3 运用场景2. 单例模式的实现2.1 C++实现2.1.1 基础要点2.1.2 懒汉式2.1.3 饿汉式2.1.4 基于CRTP(奇异的递归模板模式)的单例模式3. 致谢 1. 单例模式 1.1 定义 单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。[DP] 通常我们可以定义一个全局变量使得对象被访问,但...

EthanAndEvan的博客 848

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

单例设计模式--Singleton

  模拟场景:一个王朝只能有一个皇帝,臣子每天见的都是同一个皇帝   Emperor: 1 package com.zqz.dp.singleton; 2 /** 3 * @author Qin 场景:皇帝类,一个王朝只能有一个皇帝 4 */ 5 public class Emperor { 6 private static final Empe...

weixin_30672019的博客 78

设计模式DP(2)单态模式

设计模式DP(2)单态模式singleton 特点:一个系统内,该对象有且仅能存在一个实例            该类的实例化,交给它本身完成,外界没有创建的权力            对外封闭性 代码: ##硬汉式和懒汉式 public class Singleton{      private static Singleton instance = new Singleton()

多言数穷,不如守中。十语九中,未必称奇;一语未中,愆尤骈集。 1119

单例模式(Singleton Pattern)

设计模式(Design Pattern),简称DP。

G81948577的博客 2014

[设计模式] 5 单例模式 singleton

转处 http://blog.youkuaiyun.com/wuzhekai1985 软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书,对于每个模式,用C++写了个小例子,加深一下理解。主要参考《大话设计模式》和《设计模式:可复用面向对象软件...

weixin_30674525的博客 67

python的单例模式 Singleton

python的单例模式 Singleton 使用元类metaclass来创建单例 元类(metaclass)可以控制类的创建过程,它主要做三件事: 拦截类的创建 修改类的定义 返回修改后的类 说明一下python中几个特殊的方法和名词的解释: __new__()方法的作用是为类的对象分配内存空间; 一般不会去重写该方法,除非你确切知道怎么做,什么时候你会去关心它呢,它作为构造函数用...

u010569893的博客 375

设计模式的比喻

着楼主的帖子,在心里把GOF DP又过了一遍,感觉这种方式来学习DP很可取,不拘泥于具体而着重于思想。里面的一些内容个人觉得有些地方不太恰当,提出来供参考:创建型模式1、FACTORY—人才市场:以往是要哪个人才,就找哪个人才,效率低,现在有了人才市场,我们只需直接去人才市场挑一个好了;--人市换成猎头公司如何? 2、BUILDER—生产流水线:以前是手工业作坊式的人工单个单个的生产零件然后一步一

§为艺术而技术§ 1255

DP-單件模式(Singleton Pattern)

单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责...

weixin_30799995的博客 76

设计模式之Singleton模式

作用:只生成一个实例 public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() { System.out.println("get a new object"); } ...

aishenyan0793的博客 253

单例模式-Singleton

0.前言 在一年多前就开始学习设计模式了,主要看的是GoF的那本书《设计模式-可复用面向对象软件的基础》,很好的一本书。当时没打算开博客,所以把所有笔记都写到了OneNote上,现在想好好整理下,尽量都写到博客里面来,一方面希望对他人有帮助,一方面也是自己知识的一个积累和巩固的过程。   1.正文 在23个设计模式中,最简单应该就是单例(Singleton)模式了,个人感觉学习设计模式才...

Later equals never. 162

java设计模式 单例模式_Java设计模式-单例模式 (Singleton Pattern)

在一些程序设计中,希望对象只有一个实例,这时候就可以使用单例模式。单例模式的实现,在语法上 用一个私有的构造方法来保护类不能在外部被 new 出来,然后提供一个静态方法返回唯一的实例即可。应用场景,例如:系统配置,整个系统有一个配置对象即可,如果有配置修改,通知这个唯一的对象就好了,每次读取配置只需从这个唯一的对象中获取。下面是一些常见的写法,以及优缺点:实现方式一package cn.devdo...

weixin_35691102的博客 178

设计模式01:单例Singleton

单例模式 WHAT 单例是全局只有一个实例的代码设计方式 WHY 应用场景: 只需要一个实例,比如各种的工厂类,全局只需要一个就可以了,所以不需要让它被new出多个. 如何实现单例呢? HOW 实现单例的方式1:饿汉式(最常用的方式,并且是线程安全的) /** * 饿汉式 * 类加载到内存后,就实例化一个单例,JVM保证线程安全 * 简单实用,推荐使用! * 唯一缺点:不管用到与否,类装载时就完成实例化 * Class.forName("") * (话说你不用的,你装载它干啥) */

花哥的博客 156

设计模式的解析和实现之五-Singleton模式 单例模式

单例模式看起来也蛮简单的,就是在系统中只允许产生这个类的一个实例 注意:线程安全,采用互斥体的方式实现。   解析: Singleton模式其实是对全局静态变量的一个取代策略,上面提到的Singleton模式的两个作用在C++中是通过如下的机制实现的:1)仅有一个实例,提供一个类的静态成员变量,大家知道类的静态成员变量对于一个类的所有对象而言是惟一的 2)提供一个访问它

晴天的专栏 951
上一篇: [DP]Prototype设计模式
下一篇: [DP]Adapter设计模式
HeapStackk
博客等级 码龄12年 11粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值