【Java】单例模式

在这里插入图片描述
单例模式是面试中常考的设计模式之一
在面试中,面试官常常会要求写出两种类型的单例模式并解释原理
本文中,将从0到1的介绍单例模式究竟是什么

文章目录

  • ✍一、什么是设计模式?
  • ✍二、单例模式是什么?
  • ✍三、单例模式的类型
    • **1.饿汉式**
    • 2.懒汉式
    • 3.优化懒汉式
    • 4.指令重排
    • 5.完整代码

✍一、什么是设计模式?

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:

模式:在某些场景下,针对某类问题的某种通用的解决方案。

场景:项目所在的环境

问题:约束条件,项目目标等

解决方案:通用、可复用的设计,解决约束达到目标。

用生活中的事务来介绍:

设计模式好⽐象棋中的 “棋谱”. 红⽅当头炮, ⿊⽅⻢来跳. 针对红⽅的⼀些⾛法, ⿊⽅应招的时候有⼀些固定的套路. 按照套路来⾛局势就不会吃亏.

✍二、单例模式是什么?

单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

简单概括:

  • 单例模式能保证某个类在程序中只存在唯⼀⼀份实例,而不会创建出多个实例.

✍三、单例模式的类型

单例模式具体的实现⽅式有很多. 最常⻅的是 “饿汉” 和 “懒汉” 两种.

  • 饿汉式:在类加载过程中就创建了实例。
  • 懒汉式:在真正需要使用时,才会创建实例。

1.饿汉式

class Singleton{private static Singleton instance = new Singleton();public static Singleton getInstance(){return instance;}private Singleton(){}
}

类在加载时,就会创建一个实例。在调用时,之间返回这一实例就好。

可以简单的认为,在程序启动时就创建了实例。

2.懒汉式

class Singletonlazy{public static Singletonlazy instance = null;public Singletonlazy getInstance(){if ( instance == null){instance = new Singletonlazy();}return instance;}private Singletonlazy(){}}

这是一段存在些许问题的代码,不过可以直观的感受到两者之间的区别。

在接下来,会对如上懒汉式代码进行优化。

3.优化懒汉式

我们先将懒汉式代码放置如下

class Singletonlazy{public static Singletonlazy instance = null;public Singletonlazy getInstance(){if ( instance == null){instance = new Singletonlazy();}return instance;}private Singletonlazy(){}}

在如上懒汉式的代码中,如果在多线程情况下,就会出现一些问题

在这里插入图片描述

在多线程中,线程是抢占式执行的。
那么就会给程序带来一些问题
在这里插入图片描述

由于线程的抢占式执行,虽说不会造成空间的浪费
但是时间的消耗确实客观存在的。

那么解决这个问题,就进行加锁操作。

  public Singletonlazy getInstance(){synchronized (lock){if ( instance == null){instance = new Singletonlazy();}}return instance;}

这样加锁,就是将 if 和 new 打包成一个原子操作

但是这样也会出现问题

在这里插入图片描述

那么如何解决这个问题呢?
我们在锁的外层,在添加一个判断条件

  public Singletonlazy getInstance(){if (instance == null) {synchronized (lock){if ( instance == null){instance = new Singletonlazy();}}}return instance;}

注意:
这里的两个if条件虽然内容一样,但是意义却完全不同

  • 第一个if是判断是否要进行加锁操作
  • 第二个if是判断是否要实例创建对象

在这里插入图片描述

如上代码已经解决了多线程情况下的线程安全问题。
也解决了执行效率的问题。

但是还存在一个问题
指令重排

4.指令重排

概念:

为了使处理器内部的运算单元能尽量被充分利用,处理器可能会对输入的代码进行乱序执行优化,处理器会在计算之后将乱序执行的结果重组,并确保这一结果和顺序执行结果是一致的,但是这个过程并不保证各个语句计算的先后顺序和输入代码中的顺序一致。这就是指令重排序。

通俗的说,就是在不改变代码逻辑的条件下,通过更改指令的执行顺序,来达到优化代码的效果。

举例:

在这里插入图片描述
在这一行代码中,一个创建对象实例的过程可以在指令的角度分为三步

  1. 申请内容空间
  2. 调用构造方法(对内存空间进行初始化)
  3. 把此时内存空间的地址,赋值给instance引用

在指令重排的优化下
可能有
1 --》3 --》 2
1 --》2 --》 3
这样两种情况

1是一定在第一步的,因为是要在保证代码逻辑的前提下,才能进行指令重排。

在这里插入图片描述
那么如何解决呢?
引入volatile

public static volatile Singletonlazy instance = null;

使用volatile关键字修饰的变量,可以保证其指令执行的顺序与程序指明的顺序一致,不会发生顺序变换

5.完整代码

class Singletonlazy{public static volatile Singletonlazy instance = null;public static Object lock = new Object();public Singletonlazy getInstance(){if (instance == null) {synchronized (lock){if ( instance == null){instance = new Singletonlazy();}}}return instance;}private Singletonlazy(){}}

以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞

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

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

相关文章

线上研讨会 | 新一代数字化技术赋能机器人及智能产线行业高质量发展

随着智能制造的快速推进,制造业转型升级到了关键阶段。越来越多的企业以数字化技术搭配智能机器人及智慧产线,主动实现数字化转型。达索系统3D体验平台是实现企业数字化转型的新一代数智化平台,基于型、数字驱动、数字化连续技术,…

【深度学习基础】

打基础日常记录 CNN基础知识1. 感知机2. DNN 深度神经网络(全连接神经网络)DNN 与感知机的区别DNN特点,全连接神经网络DNN前向传播和反向传播 3. CNN结构【提取特征分类】4. CNN应用于文本 RNN基础1. RNN的本质 词向量模型word2Vec1. 自然语言…

Selenium与Metamask钱包及DApp交互及验证码破解汇总

1.LavaMoat报错: selenium.common.exceptions.WebDriverException: Message: unknown error: Runtime.callFunctionOn threw exception: Error: LavaMoat...`报错原因: 根本原因是Metamask为了用户钱包安全,而将LavaMoat 设置为了全局不可用。 报错解析文章链接: https:/…

城市定量分析学习资料大数据 gis 空间句法 Python

城市定量分析学习资料大数据 gis 空间句法 Python

Ubuntu 20.04.06 PCL C++学习记录(十六)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16 学习内容 用一组点云数据做简单的平面的分割 源代码及所用函数 源代码 #include<iostr…

IP地址到底有什么用

IP地址在计算机网络中的作用至关重要&#xff0c;它不仅是设备在网络中的唯一标识&#xff0c;更是实现网络通信、网络管理和安全的关键要素。下面&#xff0c;我们将从多个方面详细阐述IP地址的作用。 首先&#xff0c;IP地址作为设备的唯一标识&#xff0c;为网络通信提供了…

JavaScript - 你做过字符串反转吗

难度级别:初级及以上 提问概率:65% 例如有一个字符串本来是“abcde”,那么现在希望可以将其反转,最终的值是“edcba”,该如何做呢? 第一种是将字符串转为数组,利用数组的reverse方法实现元素反转,然后再将数组转为字符串,代码如下 …

面试必问!鸿蒙开发中的FA模型和Stage模型是什么?他们分别有什么区别?

鸿蒙OS&#xff08;HarmonyOS&#xff09; 是面向全场景的分布式操作系统&#xff0c;它通过创新的应用模型&#xff0c;为开发者提供了强大的应用开发框架。 在HarmonyOS的发展过程中&#xff0c;FA模型&#xff08;Feature Ability&#xff09;和Stage模型是两种重要的应用模…

静电场概述

什么是静电场 静电场是由特殊的电荷引起场。 这个特殊的电荷指&#xff1a;相对于观察者静止、且电量不随时间改变的电荷。 库仑定律 指在无限大的真空中&#xff0c;当两个静止的小带电体之间的距离远远大于本身的几何尺寸时&#xff0c;该两带电体之间的作用力。 如图所示…

二分查找 -- 力扣(LeetCode)第704题

题目 https://leetcode.cn/problems/binary-search/description/ 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例…

JavaScript代码小挑战

题目如下&#xff1a; 朱莉娅和凯特正在做一项关于狗的研究。于是&#xff0c;她们分别询问了 5 位狗主人他们的狗的年龄&#xff0c;并将数据存储到一个数组中&#xff08;每人一个数组&#xff09;。目前&#xff0c;她们只想知道一只狗是成年狗还是小狗。如果狗的年龄至少为…

SpringBoot集成Skywalking链路追踪

安装skywaling 参考&#xff1a;Centos7搭建 SkyWalking 单机版-CSDN博客 下载Agents https://archive.apache.org/dist/skywalking/java-agent/9.0.0/apache-skywalking-java-agent-9.0.0.tgz 1. 在IDEA中使用skywalking agent 在VM options中填入如下信息 -javaagent后是…

Scaling Laws 又失灵了?谷歌新研究:扩散模型不是越大越好

近年来&#xff0c;模型规模呈现出愈来愈大的趋势&#xff0c;越来越多的人相信“力大砖飞”。 OpenAI 虽然没有公布Sora的训练细节&#xff0c;但在Sora的技术报告中提到了&#xff1a; Our largest model, Sora, is capable of generating a minute of high fidelity video.…

Dify开源大语言模型(LLM) 应用开发平台如何使用Docker部署与远程访问

文章目录 1. Docker部署Dify2. 本地访问Dify3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 本文主要介绍如何在Linux Ubuntu系统以Docker的方式快速部署Dify,并结合cpolar内网穿透工具实现公网远程访问本地Dify&#xff01; Dify 是一款…

spring01:IOC(控制反转)

spring01&#xff1a;IOC&#xff08;控制反转&#xff09; 文章目录 spring01&#xff1a;IOC&#xff08;控制反转&#xff09;前言&#xff1a;一、IOC&#xff1a;inversion of control&#xff08;控制反转&#xff09;控制&#xff1a;控制对象的创建&#xff01;&#x…

IDEA中修改git的作者、邮箱名称

目录 一、查看当前git信息 1、查看git作者名称 如下图&#xff1a; 2、查看git邮箱信息 二、修改git信息 1、修改git作者名称 如下图&#xff1a; 2、修改git邮箱名称 一、查看当前git信息 1、查看git作者名称 在git控制台 或者 Terminal 输入 git config user.name …

【Linux】基础IO----系统文件IO 文件描述符fd 重定向

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解在Linux下的系统文件IO&#xff0c;知道什么是文件描述符&#xff0c;什么是重定向 > 毒鸡汤&#xff1a;白日莫闲过&#xff0c;青春不再来。 …

linux:du和df区别

文章目录 1. 概述2. du 命令2. df 命令3. 区别总结 1. 概述 du 和 df 都是 Linux 系统中用于查看磁盘空间使用情况的命令&#xff0c;但它们的功能和用法有所不同。 2. du 命令 du 是 “disk usage” 的缩写&#xff0c;用于显示文件或目录的磁盘使用情况。du 命令用于查看指…

基于Socket简单的UDP网络程序

⭐小白苦学IT的博客主页 ⭐初学者必看&#xff1a;Linux操作系统入门 ⭐代码仓库&#xff1a;Linux代码仓库 ❤关注我一起讨论和学习Linux系统 1.前言 网络编程前言 网络编程是连接数字世界的桥梁&#xff0c;它让计算机之间能够交流信息&#xff0c;为我们的生活和工作带来便利…

机器学习笔记 - 深度学习遇到超大图像怎么办?使用 xT 对极大图像进行建模论文简读

作为计算机视觉研究人员,在处理大图像时,避免不了受到硬件的限制,毕竟大图像已经不再罕见,手机的相机和绕地球运行的卫星上的相机可以拍摄如此超大的照片,遇到超大图像的时候,我们当前最好的模型和硬件都会达到极限。 所以通常我们在处理大图像时会做出两个次优选择之一:…