单例模式(线程案例)

news2025/3/4 21:47:25

单例模式可以分为两种:1.饿汉模式   2.懒汉模式


一.饿汉模式    

//饿汉模式👇
class MySingleTon{

    //因为这是一个静态成员变量,在类加载的时候,就创建了
    private static MySingleTon mySingleTon = new MySingleTon();
    
    //创建一个静态方法,方便在类外获取对象
    public static MySingleTon getMySingleTon() {
        return mySingleTon;
    }

    //创建一个私有的构造方法
    //避免通过new关键字来调用构造方法,进而创建实例
    //保证了唯一性
    private MySingleTon(){

    }
    
}

public class ThreadDemo8 {
    public static void main(String[] args) {
        MySingleTon s1 = MySingleTon.getMySingleTon();
        MySingleTon s2 = MySingleTon.getMySingleTon();
        System.out.println(s1 == s2);

    }
    
}

程序运行的结果

结果是true,说明了这两次都是获取了同一个实例!,这也说明成功实现了单例模式


因为这个对象是在类加载的时候创建,类加载是单线程的,所以线程安全。但是如果在代码中,没有使用对象,就会造成资源浪费!


二.懒汉模式

这是实现懒汉模式的代码👇

class MySingleTonLazy{
    private static MySingleTonLazy mySingleTonLazy = null;

    
    public static MySingleTonLazy getMySingleTonLazy() {
        if(mySingleTonLazy != null){
            mySingleTonLazy = new MySingleTonLazy();
        }
        return mySingleTonLazy;
    }

    
    //私有的构造方法
    private MySingleTonLazy(){


    }
}

public class ThreadDemo9 {
    public static void main(String[] args) {
        MySingleTonLazy s1 = MySingleTonLazy.getMySingleTonLazy();
        MySingleTonLazy s2 = MySingleTonLazy.getMySingleTonLazy();
        System.out.println(s1==s2);
    }
}

这个代码是有两个问题的:1.线程安全问题。2.指令重排序问题

1.线程安全问题

所以说,需要对其加锁。把这些指令打包成一个原子(整体),这样就不会出现这种情况了。


这是修改后的代码,是线程安全的!

第一个if是用来判断这个实例是否已经创建了,如果创建就直接跳过这个代码了。👆


2.指令重排序问题

mySingleTonLazy = new MySingleTonLazy()

这行代码在执行的时候,会分为3个步骤:

1.分配内存空间

2.初始化对象

3.将引用指向对象

这3个步骤可以是按132顺序执行,也可以是123顺序执行👇

如果是按132来执行的,先执行完1,然后执行3 ,在执行完3后,另一个线程也来执行,因为已经创建了对象,在if判断完后,直接跳过去了,但此时这个对象没有初始化,故而会有空指针问题


那么我们该如何解决这个问题👇

引入volatile关键字

1.防止内存可见性问题

2.解决指令重排序问题

此时这个volatile 解决指令重排序问题

 private volatile static MySingleTonLazy mySingleTonLazy = null;

那么这懒汉模式正确代码如下👇

class MySingleTonLazy {
    // 使用 volatile 修饰,保证可见性和禁止指令重排序
    private volatile static MySingleTonLazy mySingleTonLazy = null;
    private static Object locker = new Object();

    public static MySingleTonLazy getMySingleTonLazy() {
        // 第一次检查,判断实例是否已经创建
        if (mySingleTonLazy == null) {
            // 加锁,保证线程安全
            synchronized (locker) {
                // 第二次检查,防止多个线程同时通过第一次检查
                if (mySingleTonLazy == null) {
                    mySingleTonLazy = new MySingleTonLazy();
                }
            }
        }
        return mySingleTonLazy;
    }

    // 私有的构造方法,防止外部实例化
    private MySingleTonLazy() {

    }
}

public class ThreadDemo9 {
    public static void main(String[] args) {
        MySingleTonLazy s1 = MySingleTonLazy.getMySingleTonLazy();
        MySingleTonLazy s2 = MySingleTonLazy.getMySingleTonLazy();
        System.out.println(s1 == s2);
    }
}

总结:

线程安全:

饿汉模式:天生都线程安全,不用如何处理

懒汉模式:线程不安全,需要自己处理

资源利用率:

饿汉模式:那么创建出了这个实例,然后并没有使用这个实例,这就造成了资源浪费的情况

懒汉模式:用的时候,创建实例,避免不必要的资源浪费的情况

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

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

相关文章

通过多线程分别获取高分辨率和低分辨率的H264码流

目录 一.RV1126 VI采集摄像头数据并同时获取高分辨率码流和低分辨率码流流程 ​编辑 1.1初始化VI模块: 1.2初始化RGA模块: 1.3初始化高分辨率VENC编码器、 低分辨率VENC编码器: 1.4 VI绑定高分辨率VENC编码器,VI绑定RGA模块…

智慧农业中光谱相机对土壤成分的无损检测应用‌

可浏览之前发布的一篇文章:光谱相机在农业中的具体应用案例 一、土壤成分定量分析 ‌养分检测‌ 光谱相机通过捕捉土壤反射的特定波长光线,可精准检测氮、磷、钾等主要养分含量,以及有机质和水分比例。例如,不同养分对近红外波段…

DNS 详细过程 与 ICMP

🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 DNS (Domain Name System) 快速了解🦋 DNS 背景🦋 域名简介🦋 真实地址查询 —— DNS🎀 域名的层级关系&am…

学到什么记什么(25.3.3)

Upload-labs 今日重新做了一下文件上传漏洞&#xff0c;这里第一题之前采用直接抓包改后缀名.jpg为.php&#xff0c;再写入一句话<?php phpinfo();?>然后放行&#xff0c;得到图片地址&#xff08;可复制&#xff09;&#xff0c;本来直接访问图片地址即可得到敏感信息…

阿里云服务器部署项目笔记 实操 centos7.9

阿里云服务器部署项目笔记 实操 centos7.9 springboot vue elementUImysqlredis 相关的redis,mysql,nginx镜像,jdk 通过网盘分享的文件&#xff1a;docker镜像 链接: https://pan.baidu.com/s/15VwcWBP4Jy07xADuvylgQw?pwdm2g9 提取码: m2g9 配置环境 连接云服务器 安装…

win32汇编环境,窗口程序中使控件子类化的示例一

;运行效果 ;win32汇编环境,窗口程序中使编辑框控件子类化的示例一 ;窗口子类化&#xff0c;就是把某种控件&#xff0c;自已再打造一遍&#xff0c;加入自已的功能。比如弄个特殊形状的按钮&#xff0c;或只能输入特殊字符的编辑框 ;当然&#xff0c;一般来说&#xff0c;这都是…

多镜头视频生成、机器人抓取、扩散模型个性化 | Big Model weekly第58期

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 01 GLM-4-Voice: Towards Intelligent and Human-Like End-to-End Spoken Chatbot 本文介绍了一种名为GLM-4-Voice的智能且类人化的端到端语音聊天机器人。它支持中文和英文&#xff0c;能够进行实时语音对话&a…

第十四届蓝桥杯:(二分算法)字串简写

这道题我们的做法是开两个vector&#xff0c;分别把a和b字符的下标存进去&#xff0c;然后遍历a字符&#xff0c;我们要求长度必须大于等于k&#xff0c;我们可以画个图&#xff0c;也就是说b的下标减a的下标必须大于等于k-1 也就是b的下标必须大于等于a的下标k-1 我们用二分找…

制服小程序的“滑手”:禁用页面左右滑动全攻略

哈哈&#xff0c;看来你已经很聪明地发现了小程序中左右滑动的“顽皮”行为&#xff01;&#x1f604; 没错&#xff0c;我们可以通过设置 disableScroll 属性来“管教”它&#xff0c;同时结合 CSS 样式让页面既禁得住横向“乱跑”&#xff0c;又能顺畅地上下滚动。你的方案已…

webstorm的Live Edit插件配合chrome扩展程序JetBrains IDE Support实现实时预览html效果

前言 我们平时在前端网页修改好代码要点击刷新再去看修改的效果&#xff0c;这样比较麻烦&#xff0c;那么很多软件都提供了实时预览的功能&#xff0c;我们一边编辑代码一边可以看到效果。下面说的是webstorm。 1 Live Edit 首先我们需要在webstorm的settings里安装插件Live …

02 HarmonyOS Next仪表盘案例详解(一):基础篇

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; 文章目录 1. 项目概述2. 技术架构2.1 文件结构2.2 ArkTS 语言特性装饰器的使用 3. 数据结构设计3.1 接口定义3.2 数据初始化 4. 生命周期与页面路由…

张岳教授:语言模型推理与泛化研究 | ICLR 2025 特邀报告与团队专场

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; AITIME 01 ICLR 2025预讲会特邀报告 AITIME 02 ICLR 2025预讲会西湖大学张岳老师实验室专场 01 AI生成文本的自动化检测 Glimpse: Enabling White-Box Methods to Use Proprietary Models for Zero-Shot LLM-Ge…

离散傅里叶变换(Discrete Fourier Transform, DFT)及其在图像处理中的应用

离散傅里叶变换&#xff08;DFT&#xff09;及其在图像处理中的应用 什么是离散傅里叶变换&#xff1f; 离散傅里叶变换&#xff08;Discrete Fourier Transform, DFT&#xff09;是一种强大的数学工具&#xff0c;用于将离散信号从时域&#xff08;或空间域&#xff09;转换…

记一次误禁用USB导致键盘鼠标失灵的修复过程

背景说明 在电脑上插入了一个USB hub&#xff0c;然后弹窗提示&#xff1a;“集线器端口上出现电涌”&#xff0c;点开让选择“重置”或者“关闭”&#xff0c;不小心点了关闭&#xff0c;结果这个usb口就被关了&#xff0c;再插任何东西都没反应&#xff0c;找了很多办法都恢…

Apache nifi demo 实验

Apache nifi 是个数据流系统&#xff0c;可以通过配置 自定义的流程来实现数据的转换。 比如可以配置一个流程&#xff0c;读取数据库里的数据&#xff0c;再转换&#xff0c;最后保存到本地文件。 这样可以来实现一些数据转换的操作&#xff0c;而不用特地编写程序来导入导出。…

Leetcode 57-插入区间

给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表 intervals&#xff0c;其中 intervals[i] [starti, endi] 表示第 i 个区间的开始和结束&#xff0c;并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval [start, end] 表示另一个区间的开始和…

SpringCloud之Eureka、Ribbon、OpenFeign

目录1. SpringCloud Eureka&#xff08;服务注册与发现组件&#xff09;2. SpringCloud Ribbon&#xff08;负载均衡与服务调用组件&#xff09;3. SpringCloud OpenFeign&#xff08;负载均衡与服务调用组件&#xff09;SpringCloud&#xff1a;用于开发高度可扩展、高性能的分…

如何在MacOS 10.15上安装Docker Desktop

前文提到MacOS 10.15上无法通过Homebrew安装最新版本的docker&#xff0c;自然想到了去安装更早版本的docker。在MacOS上安装Docker Desktop比安装Docker Engine要更方便一些&#xff0c;具体原因可以自己搜索。通过Docker Desktop的Release notes得知最后一个支持MacOS 10.15的…

Moticon智能鞋垫传感器OpenGo:经济实用的运动科学研究与临床评估工具

Moticon智能鞋垫传感器OpenGo是运动科学研究领域的一款高性能工具&#xff0c;其无线设计和精准传感器为步态分析、平衡评估以及疾病诊断提供了稳定的数据支持。通过实时捕捉足底压力分布、动态变化及平衡状态&#xff0c;OpenGo 为研究人员和临床医生提供了深入洞察个体运动模…

打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第一天)

打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线&#xff08;第一天&#xff09; 前言最后 前言 说真的&#xff0c;用Unity工作这几年&#xff0c;经历的项目大大小小&#xff0c;对于场景的渲染算是有一定的经验&#xff0c;但涉及到HDRP高清渲染管线的了解&#xff0…