多线程单例模式

news2024/11/25 18:30:12

1、单例模式

顾名思义,单例模式能保证某个类在程序中只存在唯一一份示例,而不会创建出多个实例。就像java的JDBC编程只需要创建一个单例类DataSourece从这个DataSorce中获取数据库连接。没必要创建多个对象。

单例模式具体实现方式分为“饿汉”和“懒汉”两种。

如何保证一个程序中的单例?

1、人为约定,让大家不去new对象,给大家提供了一个方法,用的时候调用这个方法就行。

2、通过语言自身的语法限制一个类只能存在一个对象。

分析过程:

1.1、饿汉模式

代码示例:


/**
 * 单例模式
 */
public class Singleton_Hungry {
    //类的成员变量
    private static Singleton_Hungry instance=new Singleton_Hungry();
    //重写为无参构造方法,修饰符改为私有

    private Singleton_Hungry() {
    }
    //对外提供一个获取成员变量的方法
    public static Singleton_Hungry getInstance(){
        return instance;
    }
}

public class Exe_01 {
    public static void main(String[] args) {
        Singleton_Hungry singleton1=Singleton_Hungry.getInstance();
        Singleton_Hungry singleton2=Singleton_Hungry.getInstance();
        Singleton_Hungry singleton3=Singleton_Hungry.getInstance();
        Singleton_Hungry singleton4=Singleton_Hungry.getInstance();
        //打印类对象
        System.out.println(singleton1);
        System.out.println(singleton2);
        System.out.println(singleton3);
        System.out.println(singleton4);
    }
}

1.2、懒汉模式

1.2.1、单线程版

 代码示例:


public class Singleton_Lazy {
    private static Singleton_Lazy instance=null;
    private Singleton_Lazy(){

    }
    public static Singleton_Lazy getInstance(){
        //判断返回的对象是否为空
        if(instance==null){
            //创建对象
            instance=new Singleton_Lazy();
        }
        //返回单例对象
        return instance;
    }
}

public class Exe_03 {
    public static void main(String[] args) {
        //让多线程并发获取单例对象
        for (int i = 0; i < 10; i++) {
            Thread thread=new Thread(() ->{
                //获取单例
                Singleton_Lazy instance=Singleton_Lazy.getInstance();
                System.out.println(instance);
            });
            //启动线程
            thread.start();
        }
    }
}

 1.2.2、多线程版

上面的懒汉模式-单线程版的实现是不安全的。

线程安全问题发生在首次创建实例时,如果在多个线程中同时调用getInstance方法,就可能导致创建出多个实例。

一旦实例已经创建好了,后面的多线程环境调用getInstance就不再有线程安全问题了(不再修改instance)。

加上synchronized可以改善这里的线程安全问题

 

public static Singleton_DCL getInstance() {
    synchronized (Singleton_DCL.class) {
        //判断返回的对象是否为空
        //第二次判断,如果为空重新创建对象
        if (instance == null) {
            //创建对象
            instance = new Singleton_DCL();
        }
    }
    //返回单例对象
    return instance;
}

代码示例:

 


public class Singleton_Lazy {
    private static Singleton_Lazy instance=null;
    private Singleton_Lazy(){

    }
    public static Singleton_Lazy getInstance(){
        synchronized(Singleton_Lazy.class) {
            //判断返回的对象是否为空
            if (instance == null) {
                //创建对象
                instance = new Singleton_Lazy();
            }
        }
        //返回单例对象
        return instance;
    }
}

public class Exe_03 {
    public static void main(String[] args) {
        //让多线程并发获取单例对象
        for (int i = 0; i < 10; i++) {
            Thread thread=new Thread(() ->{
                //获取单例
                Singleton_Lazy instance=Singleton_Lazy.getInstance();
                System.out.println(instance);
            });
            //启动线程
            thread.start();
        }
    }
}

 

 

 1.2.3、双重检查锁(Double Check Locker)DCL

多线程版的单例模式还存在一个严重的问题:

1、当变量没有被初始化的时候,第一次创建可能会出现线程安全问题,因为多个 线程都会创建实例对象。

2、一旦实例对象被创建之后,new操作就永远不会执行了,因为获取到的实例不为null。

3、那么这时就不需要去执行加锁操作,而且加锁也是要去系统申请锁资源,如果拿到锁之后只是判断一下实例对象是否为null,如果为null什么也不干,那么锁资源也就拜拜浪费掉了

所以就出现了双重校验锁,线程安全的单例模式

代码示例:


public class Singleton_DCL {
    private volatile static Singleton_DCL instance=null;
    private Singleton_DCL(){

    }
    public static Singleton_DCL getInstance(){
        //第一次判断是否为空,目的是判断是否需要加锁
        if(instance==null) {
            synchronized (Singleton_DCL.class) {
                //判断返回的对象是否为空
                //第二次判断,如果为空重新创建对象
                if (instance == null) {
                    //创建对象
                    instance = new Singleton_DCL();
                }
            }
        }
        //返回单例对象
        return instance;
    }
}

public class Exe_04 {
    public static void main(String[] args) {
        //让多线程并发获取单例对象
        for (int i = 0; i < 10; i++) {
            Thread thread=new Thread(() ->{
                //获取单例
                Singleton_DCL instance=Singleton_DCL.getInstance();
                System.out.println(instance);
            });
            //启动线程
            thread.start();
        }
    }
}

 

 

 

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

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

相关文章

java编译与反编译

参考&#xff1a; Idea 使用技巧记录_source code recreated from a .class file by intell_hresh的博客-CSDN博客 深入理解Java Class文件格式&#xff08;一&#xff09;_昨夜星辰_zhangjg的博客-CSDN博客 实践详解javap命令&#xff08;反编译字节码&#xff09;_天然玩家…

【运筹优化】元启发式算法详解:迭代局部搜索算法(Iterated Local Search,ILS)+ 案例讲解代码实现

文章目录 一、介绍二、迭代局部搜索2.1 总体框架2.2 随机重启2.3 在 S* 中搜索2.4 ILS 三、获得高性能3.1 初始解决方案3.2 Perturbation3.2.1 扰动强度3.2.2 自适应扰动3.2.3 更复杂的扰动方案3.2.4 Speed 3.3 接受准则3.4 Local Search3.5 ILS 的全局优化 四、ILS 的精选应用…

Windows PE怎么修复系统?使用轻松备份解决!

​什么是Windows PE? Windows预先安装环境&#xff08;英语&#xff1a;Microsoft Windows Preinstallation Environment&#xff09;&#xff0c;简称Windows PE或WinPE&#xff0c;是Microsoft Windows的轻量版本&#xff0c;主要提供个人电脑开发商&#xff08;主要为OEM厂…

electron+vue3全家桶+vite项目搭建【20】窗口事件广播,通用事件封装

引入 electron中的渲染进程与主进程之间的数据交互需要利用ipc通信&#xff0c;互相订阅/通知来实现&#xff0c;我们不妨封装一个通用事件广播&#xff0c;利用自定义的事件名称来让主进程遍历窗口挨个推送对应内容&#xff0c;来实现事件的广播。 demo项目地址 实现思路 …

【计算机视觉】MaskFormer:将语义分割和实例分割作为同一任务进行训练

文章目录 一、导读二、逐像素分类和掩码分类的区别2.1 逐像素分类2.2 掩码分类2.3 区别 三、DETR四、MaskFormer五、MaskFormer用于语义和实例分割六、总结 一、导读 目标检测和实例分割是计算机视觉的基本任务&#xff0c;在从自动驾驶到医学成像的无数应用中发挥着关键作用。…

模拟电路系列分享-运放的关键参数5

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 实际运放与理想运放具有很多差别。理想运放就像一个十全十美的人&#xff0c;他学习100 分&#xff0c;寿命无限长&#xff0c;长得没挑剔&#xff0c;而实…

【c++11】移动构造的性质 和 与拷贝构造的比较(详解)

文章目录 定义性质移动构造的定义实例代码分析移动构造 与 拷贝构造的比较移动赋值 和 拷贝赋值 应用场景 定义 移动构造&#xff08;Move Constructor&#xff09;是一种特殊的构造函数&#xff0c;它通过接收一个右值引用参数来创建新对象&#xff0c;并从传入的对象中“移动…

操作系统——Windows 线程的互斥与同步

一、实验题目 Windows 线程的互斥与同步 二、实验目的 (1) 回顾操作系统进程、线程的有关概念&#xff0c;加深对 Windows 线程的理解。 (2) 了解互斥体对象&#xff0c;利用互斥与同步操作编写生产者-消费者问题的并发程序&#xff0c;加深对 P (即 semWait)、V(即 semSig…

[Spec] WiFi P2P Discovery

学习资料&#xff1a;Android Miracast 投屏 目录 学习资料&#xff1a;Android Miracast 投屏 P2P discovery Introduction Device Discovery procedures Listen State Search State Scan Phase Find Phase 总结 P2P discovery Introduction P2P发现使P2P设备能够快速…

WiSA Technologies开始接受WiSA E多声道音频开发套件的预订

美国俄勒冈州比弗顿市 — 2023年6月13日 — 为智能设备和下一代家庭娱乐系统提供沉浸式无线声效技术的领先供应商WiSA Technologies股份有限公司&#xff08;NASDAQ股票代码&#xff1a;WISA&#xff09;宣布&#xff1a;该公司现在正在接受其WiSA E开发套件的预订。WiSA E使用…

论文不详细解读(一)——MoCo系列

1. MoCo v1 论文名称&#xff1a; Momentum Contrast for Unsupervised Visual Representation Learning 开源地址&#xff1a;https://github.com/facebookresearch/moco 大佬详细解读&#xff1a;https://zhuanlan.zhihu.com/p/382763210 motivation 原始的端到端自监督方…

听说软件测试岗位基本都是女孩子在做?

“听我一朋友说&#xff0c;测试岗位基本都是女孩子做。” 不知道是不是以前“软件测试岗”给人印象是“不需要太多技术含量”的错觉&#xff0c;从而大部分外行认为从业软件测试的人员中女生应占了大多数。比如有人就觉得&#xff1a;软件测试主要是细心活&#xff0c;所以女生…

Python多任务执行方式

一、多任务的执行方式 并发&#xff1a;在一段时间内交替去执行任务&#xff08;单核CPU&#xff09;并行&#xff1a;CPU核数大于任务数 二、进程&#xff08;实现多任务&#xff09;——操作系统调度 进程是操作系统进行资源分配的基本单元一个程序至少有一个进程&#xf…

极致呈现系列之:EchartsK线图的数据量化

目录 什么是K线图K线图的特性及应用场景K线图的特性K线图的应用场景 Echarts中K线图的常用属性Vue3中创建K线图 什么是K线图 K线图是一种用于展示金融市场中股票、期货、外汇等交易品种价格走势的图表形式。它由一根根的垂直线条和水平线组成&#xff0c;能够直观地显示出一段…

OJ #378 字符串括号匹配2

题目描述 ​ 给出一个字符串&#xff0c;判断其中的左右括号是否匹配。 ​ 注&#xff1a;需同时判断左右圆括号 ( 和 ) &#xff0c;左右中括号 [和]&#xff0c;左右大括号 {和}。 ​ 不需要考虑括号之间的优先级的问题&#xff0c;也就是说&#xff0c;小括号包含大括号&…

NodeJS应届毕业生财务管理系统-计算机毕设 附源码82886

基于VueNodeJS应届毕业生财务管理系统 摘 要 随着互联网大趋势的到来&#xff0c;社会的方方面面&#xff0c;各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去&#xff0c;而其中最好的方式就是建立网络管理系统&#xff0c;并对其进行信息管理。由于现在…

合宙Air724UG Cat.1模块硬件设计指南--看门狗

概述 Air724UG 内部已经自带了看门狗&#xff0c;4秒进行一次喂狗&#xff0c;如果主芯片异常死机&#xff0c;自带的看门狗15秒左右会硬件复位主芯片。 另外主芯片死机情况下&#xff0c;reset键也可以硬重启。 通常情况下不需要外加硬件看门狗&#xff0c;如果对系统稳定性有…

FreeRTOS和uC/OS:选择入手哪个RTOS更合适?

FreeRTOS和uC/OS是两个流行的实时操作系统&#xff08;RTOS&#xff09;&#xff0c;用于嵌入式系统开发。它们有一些区别&#xff0c;但选择哪个先入手取决于你的需求和项目要求。 复杂度&#xff1a;FreeRTOS是一个相对较简单的RTOS&#xff0c;它专注于提供基本的实时调度和…

西门子Mendix 入门 3

导航页面&#xff1a;用于在应用程序中添加或修改其他页面 创建查看查看和添加公司不同部门的页面 打开导航页面&#xff0c;添加新项目 选择TaskTracke新建一个名为Department_Overview的页面&#xff0c;并选择List作为模板 创建成功 现在转到 Department_Overview页面 链接数…

揭秘2023年项目管理软件排行榜实力榜

在现代的商业世界中&#xff0c;项目管理是必不可少的一个组成部分。为了成功地管理一个项目&#xff0c;项目经理需要实施一种系统化的方法来确保项目在时间和预算的约束下成功。这就需要使用专业的项目管理软件。因此&#xff0c;项目管理软件在商业领域中扮演着至关重要的角…