当前位置: 首页 > news >正文

设计模式之单列模式

单列模式是一种经典的设计模式,在校招中最乐意考的设计模式之一~

设计模式就是软件开发中的棋谱,大佬们针对一些常见的场景,总结出来的代码的编写套路,按照套路来写,不说你写的多好,至少不会太差~

在校招中,主要考察两个设计模式:单列模式,工厂模式

本文主要讲解单列模式

单列《——》单列模式(instance)对象

一个程序中,某个类只创建出一个实列(对象)——》不能创建多个对象!

Java中的单列模式借助Java语法,保证某个类只能创建出一个实列,而不能new多次!!有些场景,本身就是要求某个概念是单列的!!

在Java语法中,如何做出单列模式的实现呢??

Java中实现单列模式的有很多种写法:起码有5/6种写法,但是课堂上主要说两种:

  • 饿汉模式(饥饿)
  • 懒汉模式(从容)

饿汉:吃完饭就立刻去洗碗

懒汉:吃完饭之后,先把碗放到一边,等到下一顿吃的时候,需要用到碗了再洗,通常认为懒汉模式更好(效率更高)

比如:中午吃饭,用了4个碗

饿汉:吃完就得把4个碗都洗了

懒汉:晚上吃饭只用2个碗,此时只需要洗2个就ok了

计算机中的列子,打开一个硬盘上的文件,读取文件内容,并显示出来:

饿汉:把文件所有的内存都读到内存中,并显示出来

懒汉:只把文件读一小部分,把当前屏幕填充上,如果用户翻页了,在读其他文件内容,如果不翻页就省下了

假设文件非常大:10G:

饿汉模式:文件可能卡半天!内存够不够??

懒汉模式:可以快速打开!

我们来看一下下述代码吧:饿汉模式:

class Singleton{//唯一的实体private static Singleton instance=new Singleton();//获取到实列的方法public static Singleton getInstance(){return instance;//单词的读操作,不涉及修改}//禁止外部new实列//此处,在类内部把实列创建好,同时禁止外部重新创建实列,此时就可以保证是单列的特性了!private Singleton(){//构造方法设为private//仅类内部使用}
}public class Main {public static void main(String[] args) {//此时s1和s2是同一个对象Singleton s1=Singleton.getInstance();Singleton s2=Singleton.getInstance();//Singleton s3=new Singleton();//此处要把new操作禁止掉,则把该类的构造方法设为private即可}
}

上述代码是线程安全的(饿汉模式),先创建好实列,随去随用~

private static Singleton instance=new Singleton();

在上述的该段代码中:被static修饰,该属性是类的熟悉,JVM中,每个类的类对象只有唯一一份,类对象里的这个成员,自然也是唯一的!!

但是对于创建的这个实列,我们可以用不到,因此:非必要不创建《——》懒汉模式

懒汉模式的核心思想:——》非必要不创建

//通过懒汉模式实现一下单列模式
class SingletonLazy{volatile private static SingletonLazy instance=null;//先置为空//只有调用getInstance才会new一个对象,如果再次调用getInstance,仍然会返回之前的实列public static SingletonLazy getInstance(){//这个条件,判定是否需要加锁,如果对象已经有了,//就不必加锁了,此时本身就是线程安全的if (instance==null){synchronized (SingletonLazy.class){//加锁,保证判定和new是一个原子操作if (instance==null){instance=new SingletonLazy();}}}return instance;//唯一}private SingletonLazy(){//构造方法设为private//类中可以访问,类外不能访问}
}public class Main1 {public static void main(String[] args) {SingletonLazy s1=SingletonLazy.getInstance();SingletonLazy s2=SingletonLazy.getInstance();//此时s1和s2是同一个实列System.out.println(s1==s2);//true}
}

显而易见,上述代码的运行结果为:

思考一下:对于前面的饿汉模式和懒汉模式的两个代码,是否线程安全??

对于饿汉模式:认为线程安全的——》只是读数据

对于懒汉模式:多线程下调用getInstance,可能会出现问题《——》线程不安全

多线程下,懒汉模式可能无法保证创建对象的唯一性!!

懒汉模式的部分代码如下:

如果是N个线程一起调用,可能就会搞出N个对象了!!

通过加锁操作《——》锁要加在哪里??多线程的代码是很复杂的,不是说只要写了加锁操作,就一定是线程安全了,只能具体问题具体分析。

加锁,是一个比较低效的操作(加锁就可能涉及到阻塞等待~)!!非必要不加锁

对于getInstance()这个方法:

在该段代码中,任何时候调用getInstance(),都会触发锁的竞争。

其实,此处的线程不安全,只出现在首次创建对象这里,一旦对象new好了,后续在调用getInstance(),就只是单纯的读操作了,就没有线程安全问题,就没有必要再加锁了!!

因此,可以在加一个if语句的判定(两个if语句的判定更加完美)

这两个if (instance==null)的代码,看起来一样,实际上,他俩的差别很大!!按照咱们之前的理解,两行代码如果紧挨着的,此时两行代码就会被迅速的执行完,近似就可以看作是“同一时机”,实际上,由于这两个if中间间隔了个synchronized,加锁可能导致阻塞,至于啥时候解除阻塞,时间不一定!!虽然两个条件相同,但是如果调用时间长了,结果也可能会不同~!!

加上volatile可以解决指令重排序的问题:

volatile private static SingletonLazy instance=null;//先置为空

小结一下,瞬间开心:

单列模式的线程安全问题:(经典面试题)

饿汉模式:天然就是安全的,只是读操作

懒汉模式:不安全,有读也有写操作

  • 加锁,把if和new变成原子操作
  • 双重if,减少不必要的加锁操作
  • 使用volatile,禁止指令重排序,保证后续线程拿到的是完整对象

相关文章:

设计模式之单列模式

单列模式是一种经典的设计模式,在校招中最乐意考的设计模式之一~ 设计模式就是软件开发中的棋谱,大佬们针对一些常见的场景,总结出来的代码的编写套路,按照套路来写,不说你写的多好,至少不会太差~ 在校招中…...

linux内核模块编译方法详解

文章目录 前言一、静态加载法1.1 编写驱动程序1.2 将新功能配置在内核中1.3为新功能代码改写Makefile1.4 make menuconfig界面里将新功能对应的那项选择为<*> 二、动态加载法2.1 新功能源码与Linux内核源码在同一目录结构下2.2 新功能源码与Linux内核源码不在同一目录结构…...

简介shell的关联数组与普通数组

本文首先介绍shell的关联数组&#xff0c;然后介绍shell的普通数组&#xff0c;最后总结它们的共同语法。 shell的关联数组 定义一个关联数组&#xff0c;并打印它的key-value对 #!/bin/sh# 声明一个关联数组 declare -A HASH_MAP# 给关联数组赋值 HASH_MAP["Tom"…...

玩转Mysql系列 - 第17篇:存储过程自定义函数详解

这是Mysql系列第17篇。 环境&#xff1a;mysql5.7.25&#xff0c;cmd命令中进行演示。 代码中被[]包含的表示可选&#xff0c;|符号分开的表示可选其一。 需求背景介绍 线上程序有时候出现问题导致数据错误的时候&#xff0c;如果比较紧急&#xff0c;我们可以写一个存储来…...

自动驾驶:轨迹预测综述

自动驾驶&#xff1a;轨迹预测综述 轨迹预测的定义轨迹预测的分类基于物理的方法&#xff08;Physics-based&#xff09;基于机器学习的方法&#xff08;Classic Machine Learning-based&#xff09;基于深度学习的方法&#xff08;Deep Learning-based&#xff09;基于强化学习…...

【uniapp/uview】u-datetime-picker 选择器的过滤器用法

引入&#xff1a;要求日期选择的下拉框在分钟显示时&#xff0c;只显示 0 和 30 分钟&#xff1b; <u-datetime-picker :show"dateShow" :filter"timeFilter" confirm"selDateConfirm" cancel"dateCancel" v-model"value1&qu…...

如何使用Docker部署Nacos服务?Nacos Docker 快速部署指南: 一站式部署与配置教程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

yocto stm32mp1集成ros

yocto stm32mp1集成ros yocto集成ros下载meta-rosyocto集成rosrootfs验证 yocto集成ros 本章节介绍yocto如何集成ros系统用来作机器人开发。 下载meta-ros 第一步首先需要下载meta-ros layer&#xff0c;meta-ros的链接如下&#xff1a;https://github.com/ros/meta-ros/tre…...

Linux 中的 chroot 命令及示例

Linux/Unix系统中的chroot命令用于更改根目录。Linux/Unix 类系统中的每个进程/命令都有一个称为root 目录的当前工作目录。它更改当前正在运行的进程及其子进程的根目录。 在此类修改的环境中运行的进程/命令无法访问根目录之外的文件。这种修改后的环境称为“ chroot监狱”或…...

oracle的redo与postgreSQL的WAL以及MySQL的binlog区别

Oracle的redo日志、PostgreSQL的WAL(Write-Ahead Log)以及MySQL的binlog(二进制日志)都是数据库的事务日志,但它们在实现和功能上有一些区别。 1. 实现方式: - Oracle的redo日志是通过在事务提交前将事务操作记录到磁盘上的重做日志文件中来实现的。 - PostgreSQL…...

进入低功耗和唤醒

休眠模式 进入休眠模式 如果使用 WFI 指令进入睡眠模式&#xff0c;则嵌套向量中断控制器 (NVIC) 确认的任意外设中断都会 将器件从睡眠模式唤醒。 如果使用 WFE 指令进入睡眠模式&#xff0c;MCU 将在有事件发生时立即退出睡眠模式。唤醒事件可 通过以下方式产生&#xff…...

【多线程】volatile 关键字

volatile 关键字 1. 保证内存可见性2. 禁止指令重排序3. 不保证原子性 1. 保证内存可见性 内存可见性问题: 一个线程针对一个变量进行读取操作&#xff0c;另一个线程针对这个变量进行修改操作&#xff0c; 此时读到的值&#xff0c;不一定是修改后的值&#xff0c;即这个读线…...

【Windows注册表内容详解】

Windows注册表内容详解 第一章节 注册表基础 一、什么是注册表 注册表是windows操作系统、硬件设备以及客户应用程序得以正常运行和保存设置的核心“数据库”&#xff0c;也可以说是一个非常巨大的树状分层结构的数据库系统。 注册表记录了用户安装在计算机上的软件和每个程…...

大数据Hadoop入门之集群的搭建

hadoop的三种运行模式 本地模式:测试本地的hadoop是否能够运行&#xff0c;用来运行官方的代码。伪分布模式:原先有人拿来测试&#xff0c;目前测试都不用这个模式了。完全分布模式&#xff1a;多台服务器组成分布式环境&#xff0c;生产环境使用 分布式主机文件同步命令 sc…...

华为云云耀云服务器L实例评测|基于云服务器的minio部署手册

华为云云耀云服务器L实例评测|基于云服务器的minio部署手册 【软件安装版本】【集群安装&#xff08;是&#xff09;&#xff08;否&#xff09;】 版本 创建人 修改人 创建时间 备注 1.0 jz jz 2023.9.2 minio华为云耀服务器 一. 部署规划与架…...

龙智携手Atlassian和JFrog举办线下研讨会,探讨如何提升企业级开发效率与质量

2023年9月8日&#xff0c;龙智将携手Atlassian和JFrog于上海举办线下研讨会&#xff0c;以“大规模开发创新&#xff1a;如何提升企业级开发效率与质量”为主题&#xff0c;邀请龙智高级咨询顾问、Atlassian认证专家叶燕秀&#xff0c;紫龙游戏上海研发中心高级项目管理主管叶凯…...

2023数学建模国赛A题定日镜场的优化设计- 全新思路及代码

背景资料关键信息和要点如下&#xff1a; 定日镜&#xff1a;塔式太阳能光热发电站的基本组件&#xff0c;由纵向转轴和水平转轴组成&#xff0c;用于反射太阳光。 定日镜场&#xff1a;由大量的定日镜组成的阵列。 集热器&#xff1a;位于吸收塔顶端&#xff0c;用于收集太…...

CSS笔记(黑马程序员pink老师前端)圆角边框

圆角边框 border-radius:length; 效果显示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Documen…...

水表电表集中远程抄表系统分析

电表水表远程抄表系统石家庄光大远通电气有限公司主要经营自动抄表,远程抄表,集中抄表,新供应信息&#xff0c;是石家庄光大远通电气有限公司自动远程抄表系统集信号采集、网络通信于一体的高性能抄表装置&#xff0c;该系统以485通讯方式读取水表电表的数据,以MBUS通讯方式读取…...

Android 通知

1. 原生Android通知的几种显示方式&#xff1a; 状态栏的图标&#xff1a;发出通知后&#xff0c;通知会先以图标的形式显示在状态栏中。 抽屉式通知栏&#xff1a;用户可以在状态栏向下滑动以打开抽屉式通知栏&#xff0c;并在其中查看更多详情及对通知执行操作。在应用或用户…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...