【设计模式】单例模式(懒汉和饿汉模式详解)

目录

1.设计模式是什么?

2.单例模式

1.概念:

2.如何设计一个单例

1.口头约定(不靠谱)

2.使用编程语言的特性来处理

3.使用"饿汉模式"设计单例

1.详细步骤

2.完整代码

 4.使用"饿汉模式"设计单例

1.详细步骤

2.完整代码

4. "饿汉模式"和"懒汉模式"的区别

 


 

1.设计模式是什么?

设计模式就是厉害的程序员根据以往的设计经验,总结出来的一套方法,类似于棋谱

2.单例模式

1.概念:

单例模式就是一种设计模式

单例在全局范围内只有一个实例化对象

例如在java通过JDBC连接数据库是使用的DateSource类,在这个类中定义了数据库的用户名,密码,连接串,定义好了以上的属性就可以通过DateSource的实例化对象获取数据路的链接

2.如何设计一个单例

1.口头约定(不靠谱)

对外提供一个方法,要求大家使用的时候,通过这个方法来获取

不能保证每个人都遵守规定,所以不采用

2.使用编程语言的特性来处理

首先我们思考一下,在Java中,哪些对象是唯一的?

1.class对象类对象,比如String.class

2.用static修饰的变量是类的成员变量

所有的实例对象中,访问的都是同一个成员变量

所以,通过类对象与static配合就可以实现单例的目的

3.使用"饿汉模式"设计单例

类似于这种随着类的加载一起完成初始化的方式,称之为"饿汉模式"

"饿汉模式"书写简单,不容易出错

1.详细步骤

1.我们让其在类加载的时候完成初始化,那么所有对象之间共享这个实例

c7d552804137499a9c6a0834d95bb94c.png

2.既然是单例,全局唯一的对象,那么就不能通过new去获取新对象

将构造方法私有化,就可以避免外部new这个类的新对象

da8db1aa1ab444849a95bf4079ddd9ff.png

3.我们对外部提供一个获取对象的方法,每次调用返回的都是同一个实例对象

将方法用ststic修饰,使其可以通过类名直接调用

f3544abeb3524c32a60cd685e3d17b68.png

2.完整代码

public class Singleton {
    public static Singleton instance = new Singleton();

    private Singleton(){};

    public static Singleton getinstance() {
        return instance;
    }
}

 4.使用"懒汉模式"设计单例

为了避免程序启动的时候浪费过多的系统资源,我们可以暂时先不初始化这个实例对象,等到程序使用的时候在对他进行初始化

1.详细步骤

最初我们并不对其进行初始化,而是在使用的时候进行初始化

8fb148ff6b354efd9e38f415d60feac4.png

但此时出现了一个问题,在多线程下去获取单例对象,出现了两个以上的实例化对象,这并不符合单例模式,说明我们的代码造成了线程不安全的现象

分析造成线程不安全的原因

8e1881351ede454799bfd3f19308a29a.png

没有保证初始化实例对象操作的原子性 

为了解决这个问题,我们给初始化的代码上锁

f4b4dbe5a4614b20ab0c8d29a5be741e.png

目前看来似乎解决了问题

但是出现了一个更严重的问题,初始化实例对象这部分代码块,在整个程序的调用过程中,只需要执行一次就足以,但是按照我们现在的写法,只要外部调用了getinstance()方法,那么所有的线程都需要参与锁竞争,都必须停下来一个个地执行,然而锁竞争是非常耗费资源的,这势必会造成大量的资源浪费,这与我们的预期也是不符的

这里我们需要知道一个知识

用户态与内核态

1a2227d139dc4d0eabded4f8658252bc.png

 为了避免过度消耗系统资源,我们可以在加一层判断

双重检查锁,这两层if语句判断的目的是不一样的

7a34745d59444027a4f8324f23fc1374.png

 第一个if语句用来判断实例对象是否是还未进行初始化,若还未初始化,因为只能初始化一次,所以加锁,只允许一个线程去执行初始化操作,其余线程等待,

第二个if语句用来判断被第一条if语句遗漏的线程,此时这个线程已经获取到instance为空,但却并未争抢到执行机会,使得其他线程先一步初始化成功对象实例,此时当这个线程终于争抢到CPU执行机会时,我们需要对它重新判断,因为此时实例对象已初始化完成,不需要再次进行初始化

到现在我们通过synchronized关键字解决了原子性,内存可见性,那么有序性我们又该如何保证呢?

那么就需要给共享变量加volatile关键字

有人不理解,上面测试明明已经是同一个实例化对象了,为什么我们还要多此一举呢?

让我们用时间线来展开说明

a07c71d0480349af951983188103d9ef.png

2.完整代码

public class Singleton01 {
    private static Singleton01 instanse = null;

    private Singleton01(){};

    public static Singleton01 getinstance() {
        if (instanse == null) {
            synchronized (Singleton01.class) {
                if(instanse == null) {
                    instanse = new Singleton01();
                }
            }
        }
        return instanse;
    }
}

4. "饿汉模式"和"懒汉模式"的区别

1.工作中可以使用 "饿汉模式",因为书写简单,不容易出错

2."饿汉模式"在程序加载的时候一起完成初始化,但由于计算机资源有限,为了节约资源,可以使用"懒汉模式"加载

3.懒汉模式在多线程情况下可能会出现不安全的问题

4.我们可以使用synchronized包裹初始化的代码块

5.但初始化实例对象的代码块只执行一次,后续线程在调用getinstance()方法时,依然会产生锁竞争,频繁的进行用户态与内核态之间的切换,非常的耗费计算机资源

6.使用双重检查锁,在最外层加一个非空校验,避免无用的锁竞争

7.此时还存有有序性的隐患,若计算机对指令重排序,可能会带来不可预计的错误

8.synchronized解决了原子性,内存可见性,但是解决不了有序性,所以给共享变量加一个volatile修饰,禁止计算机对指令的重排序

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么我在大厂待了三个月就选择离开?我聊聊应届生该选择大厂还是小公司

我在互联网大厂只待了3个月就离开了,主要原因不是大厂的福利或者薪资不够好,只是因为我发现在大厂里每天都有开不完的会,忙碌到没有自己的生活。当时我每天10点上班,晚上要工作到11甚至是12点,甚至半夜两三点都接到过工…

Flowable+React+bpmn-js实现工作流

由于新东家使用的是React,不是Vue,而自己一直想做一个关于工作流的应用出来,断断续续,花了几个月的时间,开发了工作流的功能,后面会继续完善。 技术栈 前端 前端是基于React开发的,使用了ant…

OpenCV 直方图统计函数 cv::calcHist算是彻底弄明白了

参数说明 void calcHist( const Mat* images, int nimages,const int* channels, InputArray mask,OutputArray hist, int dims, const int* histSize,const float** ranges, bool uniform true, bool accumulate false );images 图像数组。每个图像的大小要一致&#xff0c…

最强算法视频公开课!(内容硬核,完全免费!

和录友们汇报一下,代码随想录算法公开课已经更新完毕了。 由我亲自录制了140期算法视频,覆盖了 《代码随想录》纸质版上全部题目的讲解。 视频全部免费开放在B站:代码随想录 目录就在视频播放的右边,完全按照代码随想录的顺序讲…

鸿蒙Hi3861学习七-Huawei LiteOS-M(信号量)

一、简介 信号量(Semaphore)是一种实现任务间通信的机制,实现任务之间同步或临界资源的互斥访问。常用于协助一组相互竞争的任务来访问临界资源。 在多任务系统中,各任务之间需要同步或互斥实现临界资源的保护,信号量功…

面对AI“龙卷风”破坏力 白宫“软着陆”欧盟“硬防御”

ChatGPT的风靡与风险将OpenAI的CEO山姆奥特曼(Sam Altman)送进白宫,他被蹲守在美国总统府邸的记者们围追,面对5月4日白宫发起的AI风险治理会议,奥特曼很官方地给出“重要也很及时”的回应,自信的反复强调“…

chatGPT润色中英论文软件-文章修改润色器

chatGPT可以润色英文论文吗? ChatGPT可以润色英文论文,它具备自动纠错、自动完善语法和严格全面的语法、句法和内容结构检查等功能,可以对英文论文进行高质量的润色和优化。此外,ChatGPT还支持学术翻译润色、查重及语言改写等服务…

Java入门指南:从零开始的基础语法

java语言概述 Java是一种高级编程语言,最初由Sun Microsystems(现在是Oracle Corporation的一部分)在1995年推出。Java以其简单、可移植和安全的特性而闻名,并广泛用于各种应用程序开发,从桌面应用程序到移动应用程序和…

icevision环境安装

Installation - IceVision # 1. git clone 代码# pip 换源: ~/.pip/pip.conf 隐藏文件[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple [install] trusted-hostmirrors.aliyun.compip install -e .[all,dev]ImportError: cannot import name Multi…

ASEMI代理ADUM131E1BRWZ-RL原装ADI车规级ADUM131E1BRWZ-RL

编辑:ll ASEMI代理ADUM131E1BRWZ-RL原装ADI车规级ADUM131E1BRWZ-RL 型号:ADUM131E1BRWZ-RL 品牌:ADI /亚德诺 封装:SOIC-16-300mil 批号:2023 安装类型:表面贴装型 引脚数量:16 工作温度…

WPF异常处理详解

总目录 文章目录 总目录一、WPF异常1 未捕获异常2 模拟未捕获异常场景 二、处理未捕获异常1 DispatcherUnhandledException 异常捕获2 UnhandledException异常捕获3 UnobservedTaskException异常捕获4 异常捕获的综合使用 结语 一、WPF异常 1 未捕获异常 正常情况下&#xff…

又一里程碑,alibaba首推Java技术成长笔记,业内评级“钻石级”

前言 根据数据表明,阿里巴巴已经连续3年获评最受欢迎的中国互联网公司,实际上阿里巴巴无论在科技创新力还是社会创造价值这几个方面,都是具有一定代表里的。在行业内,很多互联网企业也将阿里作为自己的标杆,越来越多的…

【PSO-LSTM】基于PSO优化LSTM网络的电力负荷预测(Python代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

iOS与Android应用开发的对比:如何选择最佳开发平台?

第一章:引言 在移动应用开发领域,iOS和Android是最为流行的操作系统。选择最佳的开发平台可以使开发人员更有效地开发和发布应用程序。本文将分析iOS和Android应用开发的优缺点,并提供一些有关如何选择最佳开发平台的建议。 第二章&#xf…

Kali-linux攻击WordPress和其他应用程序

今天越来越多的企业利用SAAS(Software as a Service)工具应用在他们的业务中。例如,他们经常使用WordPress作为他们网站的内容管理系统,或者在局域网中使用Drupal框架。从这些应用程序中找到漏洞,是非常有价值的。 为…

《算经》中的百钱买百鸡问题,你会做吗?试下看看(39)

小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生。 欢迎和猫妹一起,趣味学Python。 今日主题 你知道我国历史上有个王朝叫北魏吗? 北魏(386年—534年),南北朝时期北…

AdaSparse: 自适应稀疏网络的多场景CTR预估建模

▐ 摘要 CTR(Click-through rate)预估一直是推荐/广告领域重要技术之一。近年来,通过统一模型来服务多个场景的预估建模已被证明是一种有效的手段。当前多场景预估技术面临的挑战主要来自两方面:1)跨场景泛化能力:尤其对稀疏场景&…

vscode IDE 能用的上的扩展工具功能介绍

记录分享vscode扩展,包括提升开发效率。必备。主题美化。ChatGPT等。 参考 vscode-extensions [Best] 记录分享方式,整理自己用的扩展,还有一键备份和还原方法。 ⭐快速下载和使用扩展 后面会介绍很多vscode扩展.这裡有一个技巧,…

为什么二极管具有单向导通性

大家都知道二极管具有单向导通性,比如一个双极性的信号通过二极管后会变成一个单极性的信号。 为了弄清这个问题先来看一下二极管的构成。 在纯净的硅晶体中掺入五价元素,比如磷,就形成了N型半导体,掺入的五价元素多余的电子很容…

uboot移植Linux-SD驱动代码解析

一、uboot与linux驱动 1.1、uboot本身是裸机程序 (1)狭义的驱动概念是指:操作系统中用来具体操控硬件的代码叫驱动 广义的驱动概念是指:凡是操控硬件的代码都叫驱动 (2)裸机程序中是直接使用寄存器的物理地址来操控硬件的,操作系统中必须通…