单例模式(线程案例)

单例模式可以分为两种: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);
    }
}

总结:

线程安全:

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

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

资源利用率:

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

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

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

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

相关文章

基于Matlab的多目标粒子群优化

在复杂系统的设计、决策与优化问题中,常常需要同时兼顾多个相互冲突的目标,多目标粒子群优化(MOPSO)算法应运而生,作为群体智能优化算法家族中的重要成员,它为解决此类棘手难题提供了高效且富有创新性的解决…

(2025年)工会考试该如何高效备考?有学习方法吗?

工会考试备考文章 工会考试高效备考指南 工会在维护职工权益、促进企业和谐发展中扮演着重要角色,工会考试则是选拔优秀工会工作者的关键途径。面对工会考试涉及的法律法规、组织管理以及维权服务等多方面知识,掌握科学备考方法是成功的关键。 法律法规是…

《机器学习数学基础》补充资料:向量范数

《机器学习数学基础》第1章1.5.3节介绍了向量范数的基本定义。 本文在上述基础上,介绍向量范数的有关性质。 注意: 以下均在欧几里得空间讨论,即欧氏范数。 1. 性质 实(或复)向量 x \pmb{x} x ,范数 ∥…

Unity NGUI新手向几个问题记录

1.点Button没反应 制作Button组件时,不光要挂载Button脚本,还有挂载BoxCollider BoxCollider 接收事件 2.Button点击事件的增加与删除 使用.onClick.add增加事件,使用.onClick.Remove,.onClick.RemoveAt,onClick.RemoveRang,onClick.Clear移…

servlet tomcat

在spring-mvc demo程序运行到DispatcherServlet的mvc处理 一文中,我们实践了浏览器输入一个请求,然后到SpringMvc的DispatcherServlet处理的整个流程. 设计上这些都是tomcat servlet的处理 那么究竟这是怎么到DispatcherServlet处理的,本文将…

UniApp 中封装 HTTP 请求与 Token 管理(附Demo)

目录 1. 基本知识2. Demo3. 拓展 1. 基本知识 从实战代码中学习,上述实战代码来源:芋道源码/yudao-mall-uniapp 该代码中,通过自定义 request 函数对 HTTP 请求进行了统一管理,并且结合了 Token 认证机制 请求封装原理&#xff…

【音视频】ffmpeg命令分类查询

一、ffmpeg命令分类查询 -version:显示版本 ffmpeg -version-buildconf:显示编译配置,这里指的是你编译好的ffmpeg的选项 ffmpeg -buildconf-formats:显示可用格式(muxersdemuxers),复用器和解复用器&am…

基于Windows11的DockerDesktop安装和布署方法简介

基于Windows11的DockerDesktop安装和布署方法简介 一、下载安装Docker docker 下载地址 https://www.docker.com/ Download Docker Desktop 选择Download for Winodws AMD64下载Docker Desktop Installer.exe 双点击 Docker Desktop Installer.exe 进行安装 测试Docker安装是…

C++发展

目录 ​编辑C 的发展总结:​编辑 1. C 的早期发展(1979-1985) 2. C 标准化过程(1985-1998) 3. C 标准演化(2003-2011) 4. C11(2011年) 5. C14(2014年&a…

爬虫Incapsula reese84加密案例:Etihad航空

声明: 该文章为学习使用,严禁用于商业用途和非法用途,违者后果自负,由此产生的一切后果均与作者无关 一、找出需要加密的参数 1.js运行 atob(‘aHR0cHM6Ly93d3cuZXRpaGFkLmNvbS96aC1jbi8=’) 拿到网址,F12打开调试工具,随便搜索航班,切换到network搜索一个时间点可以找…

【分享】网间数据摆渡系统,如何打破传输瓶颈,实现安全流转?

在数字化浪潮中,企业对数据安全愈发重视,网络隔离成为保护核心数据的重要手段。内外网隔离、办公网与研发网隔离等措施,虽为数据筑牢了防线,却也给数据传输带来了诸多难题。传统的数据传输方式在安全性、效率、管理等方面暴露出明…

uploadlabs经验总结

目录 一、基础上传漏洞(太过简单目前环境不可能存在) 1、抓包然后改后缀进行绕过 2、抓包然后改上传文件类型进行绕过 3、改后缀大小写绕过,以及收尾加空格,加::$DATA,加点等等 4、黑名单不完整绕过,复习后缀绕过&…

数据结构:二叉树的链式结构及相关算法详解

目录 一.链式结构的实现 1.二叉树结点基本结构,初始化与销毁: 二.链式结构二叉树的几种遍历算法 1.几种算法的简单区分: 2.前序遍历: 3.中序遍历: 4.后序遍历: 5.层序遍历(广度优先遍历B…

VSCode 移除EmmyLua插件的红色波浪线提示

VSCode 中安装插件EmmyLua,然后打开lua文件的时候,如果lua代码引用了C#脚本的变量,经常出现 “undefined global variable: UnityEngineEmmyLua(undefined-global)” 的红色波浪线提示,这个提示看着比较烦人,我们可以通…

MWC 2025 | 紫光展锐联合移远通信推出全面支持R16特性的5G模组RG620UA-EU

2025年世界移动通信大会(MWC 2025)期间,紫光展锐联合移远通信,正式发布了全面支持5G R16特性的模组RG620UA-EU,以强大的灵活性和便捷性赋能产业。 展锐芯加持,关键性能优异 RG620UA-EU模组基于紫光展锐V62…

springboot425-基于SpringBoot的BUG管理系统(源码+数据库+纯前后端分离+部署讲解等)

💕💕作者: 爱笑学姐 💕💕个人简介:十年Java,Python美女程序员一枚,精通计算机专业前后端各类框架。 💕💕各类成品Java毕设 。javaweb,ssm&#xf…

机器人“照镜子”:开启智能新时代

机器人也爱 “照镜子”? 在科技飞速发展的今天,机器人的身影越来越频繁地出现在我们的生活和工作中。它们承担着各种各样的任务,从工业生产线上的精密操作,到家庭中的清洁服务,再到危险环境下的救援工作。然而&#xf…

让 LabVIEW 程序更稳定

LabVIEW 开发的系统,尤其是工业级应用,往往需要长时间稳定运行,容不得崩溃、卡顿或数据丢失。然而,许多系统在实际运行中会遭遇内存泄漏、通信中断、界面卡顿等问题,导致生产中断甚至设备损坏。如何设计一个既稳定又易…

基于CURL命令封装的JAVA通用HTTP工具

文章目录 一、简要概述二、封装过程1. 引入依赖2. 定义脚本执行类 三、单元测试四、其他资源 一、简要概述 在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具。它支持文件的上传和下载,是综合传输工具&…

npm ERR! code 128 npm ERR! An unknown git error occurred

【问题描述】 【问题解决】 管理员运行cmd(右键window --> 选择终端管理员) 执行命令 git config --global url.“https://”.insteadOf ssh://git cd 到项目目录 重新执行npm install 个人原因,这里执行npm install --registryhttps:…