设计模式(1)——单例模式

目录

1. 单例模式的含义

2. 单例模式的四种常见方式

2.1 饿汉式经典加载方式

2.2 懒汉式加载方式

2.3 静态内部类方式加载

2.4 枚举类加载方式


1. 单例模式的含义

单例,简单来说就是单个实例,是一种常见的软件的设计模式。

一个类只实例化自己的一个实例,并且不允许再创建多余的实例,在对外提供访问时,访问的都是同一个实例对象。

2. 单例模式的四种常见方式

2.1 饿汉式经典加载方式

很好理解,饿的见到什么都吃,在单例模式中指不管用到用不到的资源,都统统加载到内存中。

优点:实现简单,实用性强,且不存在线程安全问题,是我们最常使用的一种实现方式;

缺点:不管用到与否,类加载时就完成实例化统统加载到内存,用不用都要加载,感觉有点浪费和多余,占用内存空间;

代码实现如下,这种方法实现单例模式的核心原理是JVM会且仅会将一个类加载一次到内存中去,加载一次 Mgr01 类,那么 INSTANCE 对象就被创建出来了

public class Mgr01 {
# 创建一个静态私有化 INSTANCE 对象
    private static final Mgr01 INSTANCE = new Mgr01();
# 私有化构造器,不允许其他人再创建新的类对象
    private Mgr01(){}
# 编写get方法,调用get方法即可返回已经创建好的 INSTANCE 对象
    public static Mgr01 getInstance(){
        return INSTANCE;
    }
# 此处main方法为测试方法,与设计模式无关
    public static void main(String[] args) {
        Mgr01 m1 = new Mgr01().getInstance();
        Mgr01 m2 = new Mgr01().getInstance();
        System.out.println(m1 == m2);
    }
}

我们来运行一下 main 方法,就会发现 m1 对象和 m2 对象是相等的,如下图所示

2.2 懒汉式加载方式

对比饿汉式加载,懒汉式最大的特点就是懒,我不加载,我在需要用到的时候才去进行加载。

public class Mgr02 {
// 创建一个静态 Mgr02 对象 INSTANCE,但不进行实例化,
// 并且不许使用 volatile 修饰禁止指令重排,否则可能会出错,设计知识点较深,暂不解说
    public static volatile Mgr02 INSTANCE;

// 私有化无参构造,禁止其他人访问创建新实例
    private Mgr02(){}

// 在 get 方法中进行对象的实例化,并采用双重校验实现线程安全
    public static Mgr02 getInstance(){
        // 第一次检查,如果 INSTANCE 不为空,直接返回 INSTANCE 对象
        if (INSTANCE == null){
            // 双重检查再次判断避免出现线程安全问题
            synchronized (Mgr02.class){
                if (INSTANCE == null){
                    INSTANCE = new Mgr02();
                }
            }
        }
        return INSTANCE;
    }
// 此处为测试 main方法测试线程安全
    public static void main(String[] args) {
// 循环一百次,创建一百个线程
        for (int i = 0; i < 100; i++) {
// 匿名内部类的方法创建线程对象
            new Thread(new Runnable() {
                @Override
                public void run() {
// 打印获取到的实例对象的哈希码,如果一样则说明为同一个对象
                    System.out.println(Mgr02.getInstance().hashCode());
                }
            }).start;
        }
    }
}

运行 main 方法,我们可以在控制台发现打印的对象的哈希码是一样的,说明这100个线程对象获取到的 INSTANCE 对象本质上都是同一个;

2.3 静态内部类方式加载

静态内部类是通过JVM的方式保证线程安全,JVM会保证每个类之加载一次,但类中的静态内部类是不会被加载的,只有当我们调用 get 方法时,get 方法会返回给我们一个静态内部类的INSTANCE,而INSTANCE在静态内部类中指代的就是外部类的实例对象,非常神奇,非常花哨,并且可以做到线程安全,任何人来访问get方法获取Mgr03对象的实例,获取到的都是同一个INSTANCE。

实现代码如下所示

public class Mgr03 {
// 私有化构造方法
    private Mgr03(){}
// 定义静态内部类,静态内部类不会随着类的加载而加载
    private static class Mgr03Helper{
        private final static Mgr03 INSTANCE = new Mgr03();
    }
// 定义静态 get 方法
    public static Mgr03 getInstance(){
        return Mgr03Helper.INSTANCE;
    }
// 此处为 测试 main方法,测试是否有线程安全问题
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Mgr03.getInstance().hashCode());
                }
            }).start();
        }
    }
}

运行此方法,如下图所示,所有对向的哈希码都是一样的,

 

2.4 枚举类加载方式

枚举类实现单例模式的方法更为简单,我们只需要定义一个枚举类,然后在枚举类中定义一个INSTANCE对象,枚举类会在变量的前面默认添加 "public static final",所以不需要我们再额外添加

// 定义一个枚举类 Mgr01
public enum Mgr04 {
// 定义 INSTANCE 对象
    INSTANCE;
// 此处为 main 测试方法,测试是否线程安全
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Mgr04.INSTANCE.hashCode());
                }
            }).start();
        }
    }
}

运行 main 方法,可以在控制台发现所有的对象的哈希码都是一样的,是线程安全的

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

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

相关文章

社交科技:探索Facebook的技术创新

引言 在当今数字化社会中&#xff0c;社交媒体成为了人们日常生活不可或缺的一部分&#xff0c;而Facebook作为其中的领军者&#xff0c;一直在探索和应用新的技术&#xff0c;以满足用户的需求并不断提升用户体验。本文将深入探讨Facebook在技术创新方面的努力与成就&#xf…

Fastadmin给列表数据绑定添加内容

不同及服务需要收集不同的字段&#xff0c;在服务列表处增加按钮&#xff0c;弹出管理字段列表&#xff0c;单独管理每个服务的字段。如下图&#xff0c;给不同的服务绑定不同表单字段&#xff0c;点击表单按钮弹出页面维护当前服务的字段。 实现代码 //初始化表格处添加按钮 …

吴恩达2022机器学习专项课程(一) 4.2 梯度下降实践

问题预览/关键词 本节内容梯度下降更新w的公式梯度下降更新b的公式的含义α的含义为什么要控制梯度下降的幅度&#xff1f;导数项的含义为什么要控制梯度下降的方向&#xff1f;梯度下降何时结束&#xff1f;梯度下降算法收敛的含义正确更新梯度下降的顺序错误更新梯度下降的顺…

密码杂凑算法Banana512原理详解

密码杂凑算法Banana512原理详解 黄金龙 QQ1435271638 Banana512属于杂凑函数,与美国的SHA256(安全哈希算法)类似,都属于信息摘要算法,又被称为Hash算法,Hash算法主要用于完整性校验和提高数字签名的有效性。 Hash算法的输入为任意长度的消息,输出为固定长度的Hash值,…

Java八股文(算法)

Java八股文の算法 算法 算法 逆序输出字符串 题目描述&#xff1a;输入一个字符串&#xff0c;要求逆序输出。 public static String reverseString(String s) {StringBuilder sb new StringBuilder();for (int i s.length() - 1;i > 0;i--) {sb.append(s.charAt(i));}r…

科技改变财务规划:提升企业对自动化技术的管理

在当今快节奏的市场经济中&#xff0c;财务规划与分析团队不仅仅是数字运算者&#xff0c;他们在推动业务决策、识别风险和机遇以及制定未来战略计划方面发挥着关键作用。然而&#xff0c;对于大多数企业来说&#xff0c;现实情况是财务工作过于关注历史数据分析和报告&#xf…

在 Mac 上恢复已删除文件的 4 种方法 [完整指南]

几乎每个 Mac 用户都有过因删除、格式化硬盘或清空垃圾箱而导致数据丢失的经历。当您在 Mac 上删除文件并清空垃圾箱或使用“磁盘工具”擦除功能擦除整个硬盘驱动器时&#xff0c;您可能会认为已删除的文件或已擦除的数据已永远消失。事实上&#xff0c;事实并非如此。使用正确…

电池稳定性测试系统太阳光模拟器/数字源表/测试软件

太阳光模拟器又称太阳模拟器太阳能模拟器提供一个接近自然日光的环境&#xff0c;不受环境、气候和时间等因素影响实现24小时不间断光照。太阳光模拟器又称太阳能模拟器太阳模拟器广泛应用于太阳能电池特性测试、染料敏化电池&#xff08;DSSC&#xff09;、钙钛矿电池&#xf…

JavaNIO的Buffer详解

文章目录 1. 简介2. 相关属性3. 相关方法4. 直接内存深入理解5. 零拷贝6. Java生态中的0拷贝 1. 简介 Buffer缓冲区实际上就是一个数组&#xff0c;把数组的内容和信息包装成一个Buffer对象&#xff0c;它提供了一组访问这些信息的方法。 2. 相关属性 Capacity 作为一个内存…

【YOLOv5改进系列(6)】高效涨点----使用DAMO-YOLO中的Efficient RepGFPN模块替换yolov5中的Neck部分

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ 添加yolov5_GFPN.yaml文件二、2️⃣添加extra_modules.py代码三、3️⃣yolo.py文件添加内容3.1 &#x1f393; 添加CSPStage模块 四、4️⃣实验结果4.1 &#x1f393; 使用yolov5s.pt训练的结果对比4.2 ✨ 使用…

某某消消乐增加步数漏洞分析

一、漏洞简介 1&#xff09; 漏洞所属游戏名及基本介绍&#xff1a;某某消消乐&#xff0c;三消游戏&#xff0c;类似爱消除。 2&#xff09; 漏洞对应游戏版本及平台&#xff1a;某某消消乐Android 1.22.22。 3&#xff09; 漏洞功能&#xff1a;增加游戏步数。 4&#xf…

【ripro美化】全站美化包WordPress RiPro主题二开美化版sucaihu-childV1.9(功能集成到后台)

使用介绍 1、【宝塔】删除ripro文件&#xff0c;上传最新ripro版本&#xff0c;然后上传压缩包内的ripro里面的对应文件到ripro主题对应内覆盖&#xff08;找到对应路径单个文件去覆盖&#xff09;。 2、然后上传ripro-chlid子主题美化包到/wp-content/themes路径下 3、注意顺…

STM32使用USART发送数据包指令点亮板载LED灯

电路连接&#xff1a; 连接显示屏模块&#xff0c;显示屏的SCL在B10&#xff0c;SDA在B11。 程序目的&#xff1a; 发送LED_ON指令打开板载LED灯&#xff0c;发送LED_OFF关闭板载LED灯&#xff0c;与上一个博客不同&#xff0c;这个实际上是实现串口收发文本数据包。 …

【产品经理】全面解读“数字孪生”

理解数字孪生 随着互联网技术的深入发展&#xff0c;数字孪生被越来越多地提及&#xff0c;那么数字孪生到底是什么&#xff1f;数字孪生&#xff0c;翻译自英文“Digital Twin”&#xff0c;最早在2002年&#xff0c;被从事产品生命周期管理PLM的Michael Grieves教授&#xf…

SPDZ基础使用手册(深度学习视角)

基本类型 深度学习中最常使用的便是秘密定点数sfix&#xff0c;有关定点数的高级运算协议请参阅Paper: Secure Computation With Fixed-Point Numbers. 容器类型 SPDZ的深度学习框架主要基于TensorFlow实现&#xff0c;其中使用的容器是张量Tensor&#xff0c;在库中的定义如下…

高等数学基础篇(数二)之微分方程常考题型

常考题型&#xff1a; 一、方程求解 二、综合题 三、应用题 目录 一、方程求解 二、综合题 三、应用题 一、方程求解 二、综合题 三、应用题

springcloud微服务项目,通过gateway+nacos实现灰度发布(系统不停机升级)

一、背景 灰度发布的目的是保证系统的高可用&#xff0c;不停机&#xff0c;提升用户体验。在微服务系统中&#xff0c;原有系统不下线&#xff0c;新版系统与原有系统同时在线&#xff0c;通过访问权重在线实时配置&#xff0c;可以让少量用户先应用新版本功能&#xff0c;如…

excel 提取数字字符混合文本中的数字(快捷键ctrl+e)

首先&#xff0c;已知A列数据&#xff0c;在B1单元格输入A列中的数据&#xff0c;如3*4*6 第二部&#xff1a;全选对应的B列&#xff0c;然后&#xff1a; ctrld 批量复制 CTRLE 智能复制 由此可见&#xff0c;智能提取汉字与数字混合中的数字方法 。若想分别提取3个数字&am…

量化交易入门(二十六)RSI指标实现,能盈利吗?

RSI的理论学完了&#xff0c;我们接着用苹果股票的历史数据来回测一下&#xff0c;看看这个指标靠不靠谱。 示例代码 import backtrader as bt import yfinance as yf# 定义RSI策略 class RSIStrategy(bt.Strategy):params ((rsi_period, 14),(rsi_upper, 70),(rsi_lower, 30…

新手体验OceanBase社区版V4.2:离线部署单节点集群

本文源自OceanBase用户的分享 先简单总结如下&#xff1a; 1.本文适合初学者体验OceanBase社区版 v4.2.2 2.仅需准备一台配置为2C/8G的Linux虚拟机 3.通过离线方式安装&#xff0c;以便更直观地了解安装过程 一、Linux系统准备 在宿主机(即你的windows PC电脑)上安装vbox软…