关于Java中单例模式(饿汉模式和懒汉模式)的简析

news2024/11/15 8:11:23

目录

一.什么是单例模式

二.饿汉模式和懒汉模式

饿汉模式

代码

懒汉模式

代码

关于多线程安全的问题

如何解决懒汉模式多线程安全问题

双if判断


一.什么是单例模式

简单来说,就是我们在程序中通过代码进行限制,在该程序中

只能创建一个对象

二.饿汉模式和懒汉模式

因为只能创建一个对象,所以对于我们而言就有两种方式

第一种方式

饿汉模式

让程序自动类中创建唯一的对象

在类外不能被创建

代码

class Student{

//此处在类的内部一开始就自己创建了唯一的Student对象
    public static Student st = new Student();

//提供private构造方法,让其在类外不能被调用
    private Student(){}

//提供getInstance方法,以便获取唯一的Student对象
    public static Student getInstance(){
        return st;
    }
}
public class Main {
    public static void main(String[] args) {

//此处的st2,和st3都指向唯一的st对象,还是只存在唯一一个对象
        Student st2 = Student.getInstance();
        Student st3 = Student.getInstance();
    }
}

第二种方式

懒汉模式

就是程序在自己内部不创建唯一对象

而是我们需要的时候再在类外面new那个唯一的对象

这种方式就叫做懒汉模式

代码

class Teacher{

//将te指向空,等到get的时候再进行实例化,这里是没有指向任何对象
    private static Teacher te = null;

//避免通过new的方式创建其他实例,只能通过get方式获取唯一实例
    private Teacher(){}

//通过get创建唯一对象
    public static Teacher getInstance(){
        if(te == null){
            te  = new Teacher();
        }
        return te;
    }
}
public class demo1 {
    public static void main(String[] args) {

//调用才创建对象
        Teacher te1 = Teacher.getInstance();
    }
}

关于多线程安全的问题

其实我们大体上就要记住一点

多线程同时修改同一份变量大概率就会发生线程安全的问题

所以在上述代码中

我们的饿汉模式在多线程的情况下

他不管调用几次都只是在返回已经创建好的那个唯一对象

只是相当于获取

并没有进行任何修改操作

但是在懒汉模式的多线程下

我们是进行了判断,然后创建的唯一对象,创建这个操作就是对数据进行了修改

那么多个线程同时对一个数据进行修改,那么就会发生多线程安全的问题

所以

饿汉模式没有多线程安全问题

懒汉模式多线程安全问题

如何解决懒汉模式多线程安全问题

加锁

加锁

还是(* * *)加锁

我们最优先想到的就是直接在get方法那里加上synchronized

class Teacher{
    private static Teacher te = null;
    private Teacher(){}
//直接加上一把锁
    public static synchronized Teacher getInstance(){
        if(te == null){
            te  = new Teacher();
        }
        return te;
    }
}

但是这样是会有问题的

因为此处的操作并不是原子性,那么如果是多线程进行操作,可能会出现下面的情况

 也就是说,我们可能会同时返回两个对象回去

为了避免这种情况,我们还需要加入关键字volatile(禁止指令重排序与保证可见性)

class Teacher{
//这里加上volatile 后就没有排序的问题了
    private static volatile Teacher te = null;
    private Teacher(){}
    public static synchronized Teacher getInstance(){
        if(te == null){
            te  = new Teacher();
        }
        return te;
    }
}

实际上到了这一步

我们已经解决安全的问题了

但是为了进一步提升效率,我们采取了双if判断的方式

双if判断

我们把锁加在了if判断语句这里,而取消了get方法的锁

让多个线程同时调用该方法,如果没有被创建,则执行上锁的new对象操作

如果已经被创建则返回该对象

class Teacher{
    private static volatile Teacher te = null;
    private Teacher(){}
    public static  Teacher getInstance(){

//第一个if判断,如果已经创建锁,就直接跳到最后的返回
        if(te == null){

//多个线程在调用get的时候,都卡在这里竞争这把锁
//竞争成功的创建唯一对象,并释放锁
//其他线程拿到被释放的锁之后进去查看,发现第一个线程已经创建了唯一对象
//不满足第二个if条件,又跳到最后返回
            synchronized(Teacher.class){
                if(te == null){
                    te  = new Teacher();
                }
            }
        }
        return te;
    }
}

但我个人感觉,用前面的volatile和对get方式加锁已经足够了

虽然效率比双if要低一些但已经解决了我们的多线程安全问题

双if判断只能说锦上添花吧

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

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

相关文章

【2023,学点儿新Java-17】变量与运算符:Java中的关键字及类型划分(附: 官网) | 保留字 | 字面量 | 附:Java部分关键字介绍

前情回顾: 【2023,学点儿新Java-16】编程语言的学习方法总结 | 编程的本质和架构 | 如何深度理解编程知识和技能 | 如何成为优秀的软件开发工程师 | 附:Java初学者的困惑!【2023,学点儿新Java-15】案例分享&#xff1…

机器视觉初步7:模板匹配专题

今天端午,祝各位端午安康! 今天来说说模板匹配这个专题。 模板匹配(Template Matching)是一种图像处理技术,用于在一幅图像上查找与另一幅模板图像相同的区域。模板图像和待匹配图像的大小相同。模板匹配的目的是在待…

【MongoDB大作业】MongoDB服务器的部署

【MongoDB大作业】MongoDB服务器的部署 作业要求作业步骤一、在VMware Workstations安装Linux操作系统(最小安装即可)二、安装完成后登录系统三、将ip地址设置为固定ip地址192.168.80.134四、设置虚拟网络编辑器五、使用 CRT 工具远程连接虚拟机六、下载…

《项目实战》构建SpringCloud alibaba项目(一、构建父工程、公共库、网关))

系列文章目录 构建SpringCloud alibaba项目(一、构建父工程、公共库、网关) 构建SpringCloud alibaba项目(二、构建微服务鉴权子工程store-authority-service) 文章目录 系列文章目录1、概要2、整体架构流程2.1、技术结构组成部分…

非监督学习

聚类Clustering 查看大量数据点,自动找到彼此相关或相似的数据点 K-means算法 原理 1.随机选择点,找聚类的中心位置。将点分配给簇质心 2.移动簇质心 不断重复这两个步骤 优化目标 成本函数失真函数distortion 在每次迭代中,失真成本…

极致呈现系列之:Echarts旭日图的绚丽奇观

目录 什么是旭日图旭日图的特性及应用场景旭日图的特性应用场景 旭日图常用的配置项创建基本的旭日图自定义旭日图样式样式旭日图的高级应用 什么是旭日图 旭日图是一种可视化图表,用于展示层级结构和层级之间的关系。它以一个圆形为基础,由多层的环形图…

【从零开始学习JAVA | 第七篇】API 简介

目录 前言 API介绍: 总结: 前言 这篇章为前导性文章,主要向大家介绍了什么是API,不要求掌握,感兴趣的小伙伴们可以看一看。 API介绍: API(Application Programming Interface)是指…

webpack原理之开发第一个loader

一. 搭建项目结构 整体项目结构如图: 1. 初始化包管理器package.json npm init -y 2. 打包入口文件src/main.js 3. 单页面入口public/index.html 4. 配置webpack.config.js const path require(path) const HtmlWebpackPlugin require("html-webpack-plu…

ChatBot聊天机器人学习1

1、Bot定义 能执行大量自动化、高速或机械式、繁琐的工作的计算机程序,包括但不仅限于聊天功能 2、Retrieval-based KE(知识网络)基于信息的提取。(检索的过程中有延迟,设置比较快捷的检索方式) 2.1 Int…

一看就懂的gulp操作指南:让前端工作变得更加轻松

文章目录 I. 简介什么是gulp为什么要使用gulp安装gulp II. Gulp入门任务(task)和流(stream)的概念使用gulp来处理文件基本的gulp任务(拷贝文件、压缩文件、编译Sass等) III. Gulp进阶使用插件开发面向生产的…

基于Python+tensorflow深度学习VGG-19图像风格迁移+自动去噪(MNIST数据集)机器学习+人工智能+神经网络——含全部Python工程源码

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境TensorFlow 环境 模块实现1. 图片处理2. 模型构造 系统测试工程源代码下载其它资料下载 前言 本项目基于 MNIST 数据集,使用 VGG-19 网络模型,将图像进行风格迁移,实现去噪功…

数字信号处理课程设计——调制与解调

文字目录 数字信号处理课程设计 摘要: 1绪论 1.1通信信号的调制与解调 1.2设计题目 2卷积定理和希尔伯特公式理论推导 2.1卷积定理 ​2.2希尔伯特公式 3信号DSB调制与希尔伯特解调 3.1过程框图 3.2相关理论推导 3.2.1卷积定理在调制中的应用 3.2.2希尔…

某马 qiankun 公开课 学习记录

端午早晨阳光正好,起来学习一小下 客观评价一哈:此视频适合不了解 qiankun 的朋友入门观看,更详细的使用方法还是推荐 qiankun 官网哦,老师讲的生动活泼,值得萌新一听 某马 qiankun 公开课 - bilibili ovo很多公司的…

高通Camera Log Debug 知识点

和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一、Camx UMD Log Debug二、Camx KMD log Debug三、常用缩写解释四、参考文献 一、Camx UMD Log Debug 1.1 两种方式设置camx UMD Log /vendor/etc/cam…

GPT-3.5眼中的编程语言之最:Python的卓越之处

当谈论编程语言的选择时,每个开发者都有自己的偏好和理由。作为GPT-3.5,以我的分析和学习能力,我也有自己心目中的编程语言之最。在众多编程语言中,Python在我的眼中独树一帜,是最令人着迷和受欢迎的编程语言之一。 首…

面试经典150题(1)

文章目录 前言除自身以外数组的乘积要求思路代码 跳跃游戏|要求题解代码 跳跃游戏||要求题解代码 前言 今天开始我将陆续为大家更新面试经典150题中较难理解的题目。今天我为大家分享的是,除自身以外数组的乘积、跳跃游戏| 和 跳跃游戏||。 除自身以外数组的乘积 …

【unity之UiI专题】GUI(IMGUI)详解

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:uni…

AI 绘画工具 Stable Diffusion 本地安装使用

最近要用到 AI 绘画,所以研究了下目前市面上的 AI 绘画工具,真可谓是琳琅满目,但主流的还是 Stable diffusion 和 Midjourney 两大阵营。 Midjourney 不多说,开箱即用,对新手非常友好,但不免费&#xff0c…

Linux基础(二)—— 怎么在VMware/WSL中安装Ubuntu系统

文章目录 01 | VMware安装Ubuntu02 | WSL2安装Ubuntu 虚拟机安装Linux的方式分为两种:APP安装、WSL安装 APP安装就是常见的VMware VirtualBox安装的方式,而WSL是Windows系统自带的一个虚拟机应用,可以更好的与Windows进行信息交互&#xff08…

判断是否为美丽数组

判断是否为美丽数组c思路和实现 这段代码的功能是对于给定的多个序列,判断每个序列是否是一个 beautiful 序列。没次读取当前的序列判断之后再加入下一个数字进序列。 首先,输入一个整数 t,表示测试数据组数。 对于每组测试数据,…