浅谈单例模式

ops/2024/12/21 7:32:54/

1.什么是单例模式

单例模式是设计模式的一种,那什么是设计模式呢?
欸问得好,设计模式就是对常见的业务场景总结出来的处理方法,相当于一种“套路”,类似于打王者时候,跟这个英雄对线用连招213比较好,跟那个英雄对线用连招123比较好,嗯…就是这样。

2.如何实现单例模式

实现单例模式,也就是实现单例类有两种方法,首先当我们创建一个正常类的时候,我们可以new无数个这个类的对象且不重复,例如下图:
在这里插入图片描述
看到没,student01和student02是不一样的,它们是两个完全不同的对象
但是在单例模式下,也就是单例类,你不管怎么实例化,最终实例化出来的对象完全唯一。
那么如何实现单例类呢?步骤如下:

1.在类中定义一个static修饰的变量就可以保证这个变量全局唯一(单例)
2.构造方法私有化(防止外部new对象)(那怎么外部实例这个类呢?)
3.设置一个get方法取获取对象,用static修饰,这样外部类就可以通过类名.get的方式调用

具体的实现方法有两种:“饿汉模式”和“懒汉模式”,我们下面逐一介绍:

2.1饿汉模式

代码实现:
在这里插入图片描述
按上面步骤写就是这样,接下来我们在多线程环境测试一下:
在这里插入图片描述
看,是不是外部类无法new新对象,只能用类的静态方法get获取,接下来我们删去new和打印的两行代码,测试十个线程get对象是不是同一个
在这里插入图片描述
Look!就是同一个!这个结果我已经测试了六遍了,你不服可以复制一下代码回去自己跑一下嘻嘻

2.2懒汉模式

代码实现(别急有反转):
在这里插入图片描述
接下来我们用多线程测试一下:
在这里插入图片描述

OK眼尖的大佬已经发现了多线程环境中实例化出来的对象不唯一啊,测试结果与预期不符这叫什么,嗯这就是出现了线程安全问题

问题原因详解:根本原因是cpu调度问题,线程是抢占式执行的,例如现在有两个线程,A和B,当A首先进get方法美滋滋拿到instance后!还没把instance 给store呢,线程B也进来了!由于A还没来及store它拿到的instance,instance此时为空!那么B load 的也是空, 嘿B也能通过if语句,B又get一个instance!问题就出现了…

如何解决:给那段代码加锁,确保A没执行完其他线程例如B不许进来,就好了,如下:
在这里插入图片描述
但是,还有个问题:这一加锁,每个线程进来在cpu中都要lock 然后再unlock,效率很低啊,因为这个锁我们只用一次啊,当第一次instance成功store后,后面线程load的都是那个对象,就进不去if从句,所以我们。。。。
再加个判断条件,当instance不为空直接返回就好了,不用进来再加锁再判断,然后发现不为空再返回。

于是,完整代码如下(无反转版):
在这里插入图片描述
史称DCL (Double Check Loak)双重检查锁
当然真理解不了就算了,不加,代码也能跑过,随缘。

2.3缘起

那么为什么一个叫饿汉模式一个叫懒汉模式呢,其实看代码就知道了:
饿汉模式中第一步直接就把那个static修饰的变量给实例化了,就像一个饿了很久的流浪汉,库库吃

第二个懒汉模式就是第一步我只声明一下,我懒得实例化,等到后面再说~所以叫懒汉

嗯。。。。。。。。。。。。。。。。。。。。其实我一直觉得好牵强,不如一个叫极简模式一个叫炫技模式(我的评价是)
。。。。。。。
那么好本篇写完了,(好厉害),当然了主播是实力派(OK)(KO)。


http://www.ppmy.cn/ops/143699.html

相关文章

开启数字化时代心理服务新篇章:专属线上心理咨询服务小程序

在当今快节奏的社会中,心理健康问题日益受到人们的关注。然而,传统的心理咨询模式往往受限于时间和地点,使得许多人在寻求心理帮助时感到不便。与此同时,心理课程的传播也面临着诸多挑战,如何高效地触达目标客户群体&a…

RTA_OS内核源码解析 3.9-任务激活

RTA_OS内核源码解析 3.9-任务激活 文章目录 RTA_OS内核源码解析 3.9-任务激活一、激活简介二、同步激活2.1 中断管理2.2 异常条件判断2.3 激活Task2.4 任务调度2.4.1 Os_RaiseCrossCoreISR2.4.2 Os_CrossCoreISR三、异步激活3.1 异常条件判断3.2 激活Task一、激活简介 一般将T…

《计算机组成及汇编语言原理》阅读笔记:p1-p8

《计算机组成及汇编语言原理》学习第 1 天,p1-p8 总结,总计 8 页。 一、技术总结 1.Intel 8088 microprocessor(微处理器), 1979-1988。 2.MS-DOS Microsoft Disk Operating System的缩写,是一个操作系统(operating system)。…

flutter 快速实现侧边栏

首先我们写一个侧边栏工具类&#xff0c;示例如下&#xff1a; import package:flutter/material.dart;class Sidebar extends StatelessWidget {overrideWidget build(BuildContext context) {return Drawer(child: ListView(padding: EdgeInsets.zero,children: <Widget&…

简单配置,全面保护:HZERO审计服务让安全触手可及

HZERO技术平台&#xff0c;凭借多年企业资源管理实施经验&#xff0c;深入理解企业痛点&#xff0c;为您提供了一套高效易用的审计解决方案。这套方案旨在帮助您轻松应对企业开发中的审计挑战&#xff0c;确保业务流程的合规性和透明度。 接下来&#xff0c;我将为大家详细介绍…

如何确保Java爬虫不超出API使用限制:策略示例

在数据驱动的商业环境中&#xff0c;API成为了获取数据的重要渠道。然而&#xff0c;API提供者通常会对调用频率进行限制&#xff0c;以保护服务的稳定性和响应能力。对于Java开发者来说&#xff0c;编写爬虫程序时必须考虑这些限制&#xff0c;以确保合规且高效地获取数据。本…

【从零开始入门unity游戏开发之——C#篇18】C#面向对象的封装——构造函数、`this()`构造函数链、析构函数(方法)

文章目录 一、构造函数&#xff08;方法&#xff09;1、什么是构造方法&#xff1f;2、构造方法的特点3、构造方法的例子示例代码&#xff1a;解释输出&#xff1a; 4、默认构造方法5、构造方法重载6、总结 二、this(&#xff09;构造函数链1、构造函数链的基本语法2、语法示例…

图书馆管理系统(二)基于jquery、ajax

单元三 页面搭建及功能实现 学习目标 该部分就是我们最重要的一部分&#xff0c;现在开始进行页面搭建&#xff0c;并完成一些功能的实现等等&#xff0c;最后整合完成该项目的制作。 任务3.1 登录页面 任务描述 这个任务我们将进行登录页的搭建&#xff0c;以及使用AJAX在…