设计模式(6)-单例模式

LangGraph教程8:LangGraph流式处理 流式处理可显著提升基于LLM应用的响应性。LangGraph支持两种流式模式:values模式返回每一步的完整结果,适合需要完整上下文处理的场景;updates模式仅返回增量变化,适用于实时更新需求。示例代码展示了如何用create_react_agent实现这两种模式,其中values模式完整记录处理流程,updates模式逐步输出结果。通过异步迭代输出流,开发者可以灵活选择适合应用场景的流式处理方式。 阅读详情


更多关于设计模式的文章请点击:设计模式之禅(0)-目录页


单件模式是面向对象设计模式中常用的一种设计模式,它主要的作用是使得某个对象在全局程序中只有唯一的一个实例,并且在全局中只有一个创建实例的访问点。这种模式通常采用在线程池、连接池、单一记录器等的使用和实现中。

一、单件模式的实现

单件模式(Singleton Pattern)在23种设计模式中属于比较简单的那一类,隶属于创建型模式。它的主要思想是在全局中只有一个获得实例的创建点,并且将构造函数私有,不能由外部程序随意地创建它的实例。
在这里插入图片描述

1.1 饿汉式

饿汗式的单例模式,顾名思义即在程序启动的时候将单例类直接初始化,这种最简单的一种单例模式实现:

  • SingletonObject0
/**
 * @Description: 单件模式构造(饿汗式)
 * @CreateDate: Created in 2018/11/29 10:54
 * @Author: <a href="https://blog.youkuaiyun.com/pbrlovejava">arong</a>
 */
public class SingletonObject0 {
    private static SingletonObject0 singletonObject = new SingletonObject0();
    //构造函数私有,外部类无法直接创建该对象
    private SingletonObject0(){
    }

    //全局唯一的获得实例点
    public static SingletonObject0 getInstance() {
        return  singletonObject;
    }
}

饿汗式实现有一个缺点,就是程序启动时即在全局创建了唯一的一个单例对象,但是若程序长时间都没有用过这个对象,会导致其过早初始化,浪费内存的浪费

1.2 懒汉式

懒汉式的实现指的是在程序中有使用到单例对象时才进行初始化。如果以时空角度来看,懒汉式是典型的使用时间换取空间,懒加载会需要时机判断,但是无需一开始初始化,节约内存分配;而饿汉式是典型的空间换取时间,在程序一开始初始化占用了内存,但是却无需进行时机判断。

  • SingletonObject1
/**
 * @Description: 单件模式构造(懒汉式)
 * @CreateDate: Created in 2018/11/29 10:54
 * @Author: <a href="https://blog.youkuaiyun.com/pbrlovejava">arong</a>
 */
public class SingletonObject1 {
    private static SingletonObject1 singletonObject;
    //构造函数私有,外部类无法直接创建该对象
    private SingletonObject1(){
    }

    //全局唯一的获得实例点
    public static SingletonObject1 getInstance(){
        //判断对象是否已经被创建,没有被创建则新建对象
        if( singletonObject == null){
            singletonObject = new SingletonObject1();
        }
        return singletonObject;
    }
}

通过私有化构造器并且提供唯一的实例获得点,就可以实现SingletonObject在全局中只存在唯一的一个实例了。

     @Test
        public void fun1() {
            SingletonObject1 singletonObject1 = SingletonObject1.getInstance();
            SingletonObject1 singletonObject2 = SingletonObject1.getInstance();
            System.out.println(singletonObject1+"\n"+singletonObject2);
        }

在这里插入图片描述

二、在并发下单件模式的改进

2.1 使用闭锁测试单件模式的正确性

上面写的单件模式代码似乎已经可以在全局中只产生一个实例了,可是如果在多线程模式下,以上代码还能实现单件吗?我使用了闭锁来测试并发时是否仍然能获得唯一的单件类:【关于闭锁的使用可以阅读我的一篇文章:Java并发编程(9)-使用闭锁测试并发线程安全性】

 @Test
    public void concurrentTest(){
        //开始闭锁
        CountDownLatch startLatch = new CountDownLatch(1);
        for (int i = 0; i < 5; i++) {
            new Thread() {
              public void run(){
                  try {
                      //线程运行至闭锁处等待
                      startLatch.await();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  //5个线程并发执行任务
                 new MyTask().run();
                }

            }.start();
        }

        //线程全部集结在闭锁下,开锁
        startLatch.countDown();
    }

    //任务类
    public class MyTask implements Runnable{

        @Override
        public void run() {
            //获得单例类
            SingletonObject1 instance = SingletonObject1.getInstance();
            //打印地址
            System.out.println(instance);
        }
    }

在这个测试中,我只让5个线程去并发地获得单件类实例,可是却出现了问题,单件的实例并不唯一了:
在这里插入图片描述

2.2 同步式

要使得单件模式在并发条件下仍然正确,最简单的方式就是使用同步锁来限制同时读取实例的线程数,这个做法很安全,但是会影响速度:

  • SingletonObject3
/**
 * @Description: 单件模式构造(同步式)
 * @CreateDate: Created in 2018/11/29 10:54
 * @Author: <a href="https://blog.youkuaiyun.com/pbrlovejava">arong</a>
 */
public class SingletonObject3 {
    private static SingletonObject3 singletonObject;
    //构造函数私有,外部类无法直接创建该对象
    private SingletonObject3(){
    }

	 //全局唯一的获得实例点
    public static synchronized SingletonObject3 getInstance(){
        //判断对象是否已经被创建,没有被创建则新建对象
        if( singletonObject == null){
            singletonObject = new SingletonObject1();
        }
        return  singletonObject;
    }
2.3 二重检查加锁

对于同步锁而言,还可以使用更加轻量的volatile关键字来实现线程之间对实例状态的检查加锁:

public class SingletonObjec4 {
   private volatile static SingletonObject4 singletonObject;

   //构造方法私有化,只能在本类中调用构造方法
   private SingletonObject(){
   }
   /**
    *@description 获得全局唯一的实例(二重检查加锁)
    *@author arong
    *@date 2018/11/27
    *@param:
    *@return com.iteason.singletonPattern.SingletonObject
    */
   public static SingletonObject4 getInstance(){
       //一重检查
       if(singletonObject == null) {
     	  	//加锁
           synchronized (singletonObject){
               //二重检查
               if (singletonObject == null) {
            	   singletonObject = new SingletonObject();
               }
           }
       }
           return singletonObject;
   }
}
2.4. 典型错误-缺失volatile

在双重检查加锁的单例模式中,如果单例对象不使用volatile进行修饰的话,因为创建对象的重排序的原因,将初始化和分配内存这两个步骤颠倒,那么会导致创建对象时的误判,导致返回一个空对象。

一个错误的双重检查加锁Demo

public class Singleton {
    private Singleton instance = null;
    private Singleton() {}
    
    public Singleton getInstance() {
        // 先判断对象是否已经初始化
        if (instance == null) {
            synchronized (instance) {
                // 确定对象没有初始化
                if (instance == null) {
                    return new Singleton();
                }
            }
        }
        return object;
    }
}

上述代码发生错误的原因在于return new Singleton()这行代码,这行代码并不是一个原子性的的操作,它可以分为以下三个阶段:

1.分配对象内存
2.初始化对象
3.将对象引用到内存空间

其中,在将对象引用到内存空间时,instance就不等于null了。

在单线程情况下,2和3指令发生重排序,但是由于as-if-serial语义,其执行结果也是不变的:
在这里插入图片描述
在多线程情况下,有可能会发生以下的执行顺序,导致程序执行结果出错:
A线程在执行到第3步的时候即设置instance指向内存空间,此时B线程判断其不为空,返回instance,但此时instance并未进行初始化,所以出现了错误,返回了一个空对象。
在这里插入图片描述

解决该问题的方法是在instance前加上volatile修饰,这样就能禁止重排序。
在这里插入图片描述

基于YOLOv8的水果新鲜程度检测系统设计与实现 数据采集与预处理模块:负责收集水果图像数据并进行标注和增强深度学习模型:基于YOLOv8的目标检测模型新鲜度评估模块:根据检测结果评估水果新鲜程度用户界面:提供友好的交互界面系统集成:将各模块整合为完整系统水果新鲜程度检测需要包含多种水果在不同新鲜度状态下的图像数据集。:包含5种常见水果(苹果、香蕉、橙子、葡萄、草莓)在不同新鲜度下的图像包含约8,000张图像,分为新鲜和腐烂两类AgriVision:大型农业图像数据集,包含水果检测和分类任务Fruit-360:包含120种水果的高质量图像。 阅读详情

相关推荐

微信小程序推送微信服务号模板消息

微信小程序中发送微信服务号模板消息,无需用户手动确认订阅,无需绑定开放平台,无需使用UnionId。

qq_20751269的博客 1561

设计模式6——单例模式

是一种创建型模式。1、保证一个类仅有一个实例,并提供一个访问它的全局访问点; 2、在一些场景下,类的实例化应该由自己决定,而不是外部决定的; 3、通常我们可以定义一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的方法就是,让此对象自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法; 4、单例模式封装了他的唯一实例,所以它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。

weixin_43687024的博客 554

利用Ghidra与SVD插件实现STM32固件深度逆向分析

本文详细介绍了如何利用Ghidra逆向工程框架结合SVD插件,实现对STM32固件(.bin文件)的深度逆向分析。通过加载描述芯片外设寄存器的SVD文件,Ghidra能将晦涩的硬件地址操作转换为可读的寄存器符号,极大提升了对嵌入式固件中通信协议、安全校验等关键逻辑的分析效率。文章涵盖了从Java环境搭建、工具配置到实战逆向解析的完整流程。

peach的博客 945

设计模式【6】单例模式

单例模式如此设计的原因大多因为两点: 1. 对象庞大:这些对象往往大至几十甚至上百MB,实例化如此庞大对象的逻辑往往极度复杂且易错,并且必然耗时良久; 2. 复用性高:对象会被频繁的访问。.........

说淑人的所思所想 166

3D-IC测试挑战与Tessent解决方案解析

3D-IC技术通过硅通孔(TSV)实现芯片垂直堆叠,是延续摩尔定律的关键路径。该技术面临三大核心挑战:KGD标准严苛化要求测试覆盖率达99.5%以上,存储器测试需兼容LPDDR/HBM等多种协议,逻辑堆叠需解决TSV互连的电气特性和时序验证问题。Mentor Tessent平台采用混合测试架构,结合压缩扫描测试(ATPG)和内建自测试(BIST)技术,实现100x测试数据压缩比和99.97%的TSV缺陷检出率。这些创新方案在移动SoC和高性能计算芯片中已获验证,测试时间缩短73%,缺陷逃逸率降低77%。随着

weixin_30621711的博客 376

基于Python的网贷平台数据爬虫实战:Scrapy+Selenium+反反爬策略

python复制下载# items.py本文详细介绍了如何使用Python构建一个完整的网贷平台数据爬虫系统,涵盖了从基础爬取到高级反反爬策略的全套解决方案。我们使用了Scrapy框架作为基础,结合Selenium处理动态内容,实现了多种反反爬策略,并探讨了分布式爬虫的实现方式。机器学习识别验证码基于深度学习的网页结构变化检测自动化行为模拟的更精细控制基于Kubernetes的弹性爬虫集群。

2201_76125261的博客 1560

设计模式の单例模式(6种)

设计模式简介 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大

梦里蓝天 537

CKA-题库-简洁参考答案-反复练习20遍-必过!!!

新版CKA考试已于2020年9月1日正式上线! 考试模式:线上考试 考试时间:2小时 认证有效期:3年 软件版本:Kubernetes v1.19 重考政策:可接受1次重考 经验水平:中級 题目数量:17题 题库量小:随机的题目重复率极高 考试时可打开两个浏览器Tab,一个是考试窗口,一个用来查阅官方文档](https://kubernetes.io/docs/) 01 Task - 英文 Create a new ClusterRole named deployment-clusterrole tha.

随笔记录-分享&记忆 7319

Go设计模式(6)-单例模式

1.说明 前面5篇文章讲解了设计模式的语法、面向对象分析、原则、代码编写、类图表示法,从本文开始讲述23种设计模式。 后面会按照创建型、结构型、行为型的顺序来写 创建型5个:单例模式、简单工厂、工厂模式、建造者模式、原型模式 ,主要解决“对象的创建”问题 结构型7:代理模式、桥接模式、装饰器模式、适配器模式、门面模式 、组合模式、享元模式,主要解决“类或对象的组合或组装”问题 行为型11:观察者模式、模板模式、策略模式、职责链模式、状态模式、迭代器模式、访问者模式、备忘录模式、命令模式、解释器

772

Android 12.0 SystemUI下拉状态栏定制化之隐藏下拉通知栏布局功能实现(二)

在12.0的系统定制化开发中,由于从12.0开始SystemUI下拉状态栏和11.0的变化比较大,所以可以说需要从新分析相关的SystemUI的 布局,然后做分析来实现不同的功能,今天就开始实现关于隐藏SystemUI下拉状态栏中的通知栏布局系列二,去掉下拉状态栏中 通知栏部分 白色的圆角背景

安卓兼职framework和app工程师的博客 1636

基于YOLOv10的PCB电子元件智能识别系统设计与实现

数据预处理模块:负责对原始PCB图像进行标注、增强和格式转换模型训练模块:基于YOLOv10架构进行模型训练和优化推理检测模块:加载训练好的模型进行实时检测用户界面模块:提供友好的交互界面,方便用户操作和结果可视化YOLO(You Only Look Once)系列算法自2016年提出以来,经历了多次迭代更新。YOLOv1-v3:奠定了YOLO系列的基础架构YOLOv4-v7:引入大量优化技巧和网络结构改进YOLOv8-v9:进一步优化模型结构和训练策略YOLOv10。

YOLO 156

6. 设计模式之《单例模式》

单例模式,顾名思义就是只有一个对象,考虑一下什么时候只需要一个对象?常见比如日志对象,这种最好就是一个项目中一个对象。 class Log { public: Log* getLog() { if(nullptr == m_log) log = new Log(); return m_log; } private: st...

feng__shuai的博客 285

Win11此电脑怎么放在桌面上?Win11此电脑如何显示在电脑桌面上?

相信用习惯Win10的用户都喜欢电脑电脑桌面上的此电脑,但是很多用户更新完Win11正式版以后,发现桌面只有回收站和Microsoft Edge图标,没有此电脑。那么,Win11此电脑要如何显示呢?下面小编为大家简单介绍一下操作方法!5、桌面图标设置窗口,点击勾选计算机,然后点击确定,桌面就可以显示此电脑图标了。1、桌面空白处,点击右键,在打开的菜单项中,选择显示设置;4、个性化 - 主题,相关设置下,点击桌面图标设置;3、右侧点击主题(安装、创建、管理);2、设置窗口,左侧点击个性化;

shengyin714959的博客 13万+

设计模式6-单例模式

  单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且他可以提供一个访问该实例的方法。   直接代码: public class Singleton { //作用:private 私...

weixin_30808575的博客 76

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【设计模式】单例模式的6种写法

// 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 // 单例模式的6种写法 // 1.饿汉模式 public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstan

乔培宸的博客 372

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

单例模式之es3与es6双版本(设计模式)

定义 保证一个类仅有以一个实例,仅能被实例化/创建一次,并提供全局的访问点。 单例模式是一种重要的设计模式,有些对象我们只需要创建一个,比如浏览器的window对象,模态对话框。实现这种设计模式其实很简单,最重要的是在创建实例的时候,用一个标记变量判断实例是否已经创建。 普通青年写法 function Singleton(name){ ...

weixin_34367257的博客 91

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java 设计模式——单例模式6种写法:从原理到 SpringBoot 落地

本文全面解析Java单例模式的6种实现方式,包括静态内部类、双重校验锁、枚举等。重点分析了各方案的优缺点、适用场景及实现原理,特别强调线程安全、懒加载和防破坏(反射/反序列化)等关键问题。其中静态内部类作为日常开发首选,双重校验锁适合高并发场景,枚举单例则是最安全的防破坏方案。文章还通过代码示例直观展示实现细节,为开发者提供从理论到实践的系统指导。

qq_46601365的博客 1900

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

第六章 单例模式 为什么需要单例模式? 有些对象只需要一个,例如:线程池、缓存和日志对象。 单例模式的特点: 保证一个类仅有一个实例,并提供一个访问它的全局访问点; 防止一个全局使用的类频繁地创建与销毁; 判断系统是否已经有这个单例,如果有则返回,如果没有则创建; 构造函数是私有的,若提供公共的构造函数 ,则可以构造多个该类对象。 1.1 饿汉式单例 在JVM启动便加载,优点是代码简单,缺点是存在启动时的性能消耗、若未使用该对象,会浪费资源等问题。 package headfirst.designpa

qq_36188127的博客 203

设计模式(6)单例模式

单例模式是一个比较简单的设置模式,在我们编码的过程中,有一些类会经常使用到,但是只需要一个实例就可以实现,如果大量的创建实例,可能会导致许多问题,如资源的大量使用、程序异常等。 这时候就轮到单例模式展现他的力量了。 单例模式确保了一个类只有一个实例,并提供了一个全局的访问点,下面我们看一个最简单的单例模式。 public class Singleton { private ...

weixin_30246221的博客 73

设计模式之一文讲清楚单例模式及6种写法

目录单例模式介绍 单例模式的使用场景 优点 缺点单例模式的6种写法 一、饿汉式:1、在静态变量里,直接初始化实例。 二、懒汉式:1、在静态变量里,只声明变量。2、在第一次获取实例的请求getInstance()到来时,才创建实例。 三、synchronized懒汉式:线程安全 四、双重校验锁+volati...

小明的Java问道之路 1291

设计模式 之 单例模式 6种实现方式

单例模式 介绍 **意图:**保证一个类仅有一个实例,并提供一个访问它的全局访问点。 **主要解决:**一个全局使用的类频繁地创建与销毁。 **何时使用:**当您想控制实例数目,节省系统资源的时候。 **如何解决:**判断系统是否已经有这个单例,如果有则返回,如果没有则创建。 **关键代码:**构造函数是私有的。 应用实例: 1、一个班级只有一个班主任。 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来

weixin_34854320的博客 228

设计模式——单例模式

学习了这么长的时间,设计模式却还是浅尝辄止,而且最近在回顾Vue知识的时候,发现了很多常见的设计模式:观察者啊,单例啊什么的。让我意识到,如果想要去读懂Vue底层的话,设计模式的思想是必不可少的。虽然是在学前端,但是准备通过java来学习设计模式,因为毕竟java是一个强类型的语言,通过java能更直观的去学习设计模式的思想。同时也会尽量去将设计模式通过JavaScript的方式实现出来。字面上来看,就是只有一个实例的模式。简单来说,单例模式就是在整个系统中,保持一个实例,不生成新实例的模式。当然并不是说仅

qq_45670042的博客 1248

JAVA设计模式之单例模式(6种实现)

转自http://www.kongzid.com/archives/design2,单例对象的类只能允许一个实例存在。 许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。 单例的实现主要是通过以下两个步骤: 将该类的构...

孔子说 1194

【学习设计模式6】单枪匹马只身一人——单例模式

单例模式是结构最简单的设计模式之一,也是最普遍应用的设计模式之一。 简单但是重要,唯一所以特别。

Aiky哇 351

headfirst设计模式(6)—单例模式

单例入门浅析 HeadFirst的原文是由一个巧克力锅炉的例子引入了经典的单例模式,具体例子不赘述,直接进入经典单例模式的贴代码环节(注意:以下所有代码为了方便区分和源代码稍有不同) 经典的单例模式(线程不安全): public class ClassicSingleton { private static ClassicSingleton UNIQUE_INSTANCE; ...

qq_38455566的博客 251

【设计模式系列6】单例模式的8种写法及如何防止单例被破坏

单例模式的写法懒汉模式恶汉模式 懒汉模式 恶汉模式

zwx900102的博客 2590
上一篇: 设计模式(5)-适配器模式
下一篇: 设计模式(7)-模板方法模式
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值