当前位置: 首页 > 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;并在其中查看更多详情及对通知执行操作。在应用或用户…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...