【设计模式】三、概述分类+单例模式
文章目录
- 概述
- 设计模式类型
- 单例模式
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步方法)
- 懒汉式(线程安全,同步代码块)
- 双重检查
- 静态内部类
- 枚举
- 单例模式在 JDK 应用的源码分析
- 总结
概述
设计模式类型
- 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式
- 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式
- 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter 模式)、状态模式、策略模式、职责链模式(责任链模式)
单例模式
采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
该类只提供一个取得其对象实例的方法(静态方法)
比如 Hibernate 的 SessionFactory,它充当数据存储源的代理,并负责创建 Session 对象。SessionFactory 并不是轻量级的,一般情况下,一个项目通常只需要一个 SessionFactory 就够,这是就会使用到单例模式。
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步方法)
- 懒汉式(线程安全,同步代码块)
- 双重检查
- 静态内部类
- 枚举
饿汉式(静态常量)
public class SingletonTest01 {public static void main(String[] args) {//测试Singleton instance = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance == instance2); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}//饿汉式(静态变量)class Singleton {//1. 构造器私有化, 外部能newprivate Singleton() {}//2.本类内部创建对象实例private final static Singleton instance = new Singleton();//3. 提供一个公有的静态方法,返回实例对象public static Singleton getInstance() {return instance;}}
优缺点:
- 优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
- 缺点:在类装载的时候就完成实例化,没有达到 Lazy Loading 的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费
- 这种方式基于 classloder 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,在单例模式中大多数都是调用 getInstance 方法,但是导致类装载的原因有很多种,因此不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 就没有达到 lazy loading 的效果
- 结论:这种单例模式可用,可能造成内存浪费
饿汉式(静态代码块)
public class SingletonTest02 {public static void main(String[] args) {//测试Singleton instance = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance == instance2); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}//饿汉式(静态变量)class Singleton {//1. 构造器私有化, 外部能newprivate Singleton() {}//2.本类内部创建对象实例private static Singleton instance;static { // 在静态代码块中,创建单例对象instance = new Singleton();}//3. 提供一个公有的静态方法,返回实例对象public static Singleton getInstance() {return instance;}}
优缺点:
- 这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。
- 结论:这种单例模式可用,但是可能造成内存浪费
懒汉式(线程不安全)
public class SingletonTest03 {public static void main(String[] args) {System.out.println("懒汉式1 , 线程不安全~");Singleton instance = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance == instance2); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}class Singleton {private static Singleton instance;private Singleton() {}//提供一个静态的公有方法,当使用到该方法时,才去创建 instance//即懒汉式public static Singleton getInstance() {if(instance == null) {instance = new Singleton();}return instance;}
}
懒汉式(线程安全,同步方法)
public class SingletonTest04 {public static void main(String[] args) {System.out.println("懒汉式2 , 线程安全~");Singleton instance = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance == instance2); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}// 懒汉式(线程安全,同步方法)
class Singleton {private static Singleton instance;private Singleton() {}//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题//即懒汉式public static synchronized Singleton getInstance() {if(instance == null) {instance = new Singleton();}return instance;}
}
优缺点:
- 解决了线程安全问题
- 效率太低了,每个线程在想获得类的实例时候,执行 getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接 return 就行了。方法进行同步效率太低
- 结论:在实际开发中,不推荐使用这种方式
懒汉式(线程安全,同步代码块)
优缺点:
- 不推荐使用
- 线程安全问题无法解决
双重检查
public class SingletonTest06 {public static void main(String[] args) {System.out.println("双重检查");Singleton instance = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance == instance2); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}// 懒汉式(线程安全,同步方法)
class Singleton {private static volatile Singleton instance;private Singleton() {}//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题//同时保证了效率, 推荐使用public static synchronized Singleton getInstance() {if(instance == null) {synchronized (Singleton.class) {if(instance == null) {instance = new Singleton();}}}return instance;}
}
优缺点:
- Double-Check 概念是多线程开发中常使用到的,如代码中所示,我们进行了两次 if (singleton == null)检查,这样就可以保证线程安全了。
- 这样,实例化代码只用执行一次,后面再次访问时,判断 if (singleton == null),直接 return 实例化对象,也避免的反复进行方法同步.
- 线程安全;延迟加载;效率较高
- 结论:在实际开发中,推荐使用这种单例设计模式
静态内部类
public class SingletonTest07 {public static void main(String[] args) {System.out.println("使用静态内部类完成单例模式");Singleton instance = Singleton.getInstance();Singleton instance2 = Singleton.getInstance();System.out.println(instance == instance2); // trueSystem.out.println("instance.hashCode=" + instance.hashCode());System.out.println("instance2.hashCode=" + instance2.hashCode());}}// 静态内部类完成, 推荐使用
class Singleton {private static volatile Singleton instance;//构造器私有化private Singleton() {}//写一个静态内部类,该类中有一个静态属性 Singletonprivate static class SingletonInstance {private static final Singleton INSTANCE = new Singleton(); }//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCEpublic static synchronized Singleton getInstance() {return SingletonInstance.INSTANCE;}
}
优缺点:
- 这种方式采用了类装载的机制来保证初始化实例时只有一个线程。 静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,调用 getInstance 方法,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化。
- 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM 帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
- 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
- 结论:推荐使用.
枚举
public class SingletonTest08 {public static void main(String[] args) {Singleton instance = Singleton.INSTANCE;Singleton instance2 = Singleton.INSTANCE;System.out.println(instance == instance2);System.out.println(instance.hashCode());System.out.println(instance2.hashCode());instance.sayOK();}
}//使用枚举,可以实现单例, 推荐
enum Singleton {INSTANCE; //属性public void sayOK() {System.out.println("ok~");}
}
优缺点:
- 这借助 JDK1.5 中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
- 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式
- 结论:推荐使用
单例模式在 JDK 应用的源码分析
java.lang.Runtime 就是经典的单例模式(饿汉式)

总结
- 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
- 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
- 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session 工厂等)
相关文章:
【设计模式】三、概述分类+单例模式
文章目录 概述设计模式类型 单例模式饿汉式(静态常量)饿汉式(静态代码块)懒汉式(线程不安全)懒汉式(线程安全,同步方法)懒汉式(线程安全,同步代码块)双重检查静态内部类枚举单例模式在 JDK 应用的源码分析 …...
手把手教学 Springboot+ftp+下载图片
简单教学,复制即用的Ftp下载图片 引入配置包 <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><grou…...
LaaS LLM as a service
LaaS LLM as a service 核心构成GPT 产业链如何进行商业化LLM(Large Language Model) 发展和趋势LLM(Large Language Model) 对于行业公司的分层LLM(Large Language Model) 的机遇和挑战 LaaS LLM as a service 核心构成 计算:算力模型:算法输入&…...
数据结构与算法(一)数组的相关概念和底层java实现
一、前言 从今天开始,笔者也开始从0学习数据结构和算法,但是因为这次学习比较捉急,所以记录的内容并不会过于详细,会从基础和底层代码实现以及力扣相关题目去写相关的文章,对于详细的概念并不会过多讲解 二、数组基础…...
歌曲推荐《最佳损友》
最佳损友 陈奕迅演唱歌曲 《最佳损友》是陈奕迅演唱的一首粤语歌曲,由黄伟文作词,Eric Kwok(郭伟亮)作曲。收录于专辑《Life Continues》中,发行于2006年6月15日。 2006年12月26日,该曲获得2006香港新城…...
多元共进|科技促进艺术发展,助力文化传承
科技发展助力文化和艺术的传播 融合传统与创新,碰撞独特魅力 一起来了解 2023 Google 开发者大会上 谷歌如何依托科技创新 推动艺术与文化连接 传承和弘扬传统文化 自 2011 年成立以来,谷歌艺术与文化致力于提供体验艺术和文化的新方式,从生成…...
Java集合(Collection、Iterator、Map、Collections)概述——Java第十三讲
前言 本讲我们将继续来讲解Java的其他重要知识点——Java集合。Java集合框架是Java编程语言中一个重要的部分,它提供了一套预定义的类和接口,供程序员使用数据结构来存储和操作一组对象。Java集合框架主要包括两种类型:一种是集合(Collection),存储一个元素列表,…...
topscoding主题库模板题
目录 模板题 【模板题】分因数(P1101) 【模板题】区间素数 III(P1113) 进制转换 III (任意转任意) (P2463) AB Problem(高精度加法) A-B Problem(高精度减法&…...
Linux--进程间通讯--FIFO(open打开)
1. 什么是FIFO FIFO命名管道,也叫有名管道,来区分管道pipe。管道pipe只能用于有血缘关系的进程间通信,但通过FIFO可以实现不相关的进程之间交换数据。FIFO是Linux基础文件类型中的一种,但是FIFO文件在磁盘上没有数据块,…...
哪里可以了解轻量的工作流引擎?
如果想要实现高效率的办公,可以使用轻量的工作流引擎低代码技术平台。随着工作量日益繁重起来,传统的办公制作方式已经无法满足现实需要的,采用轻量级的表格制作工具,就能在无形中缓解办公压力,创造更高效、灵活、优质…...
lvs负载均衡、LVS集群部署
四:LVS集群部署 lvs给nginx做负载均衡项目 218lvs(DR 负载均衡器) yum -y install ipvsadm(安装这个工具来管理lvs) 设置VIP192.168.142.120 创建ipvsadm的文件用来存放lvs的规则 定义策略 ipvsadm -C //清空现有…...
如何应对核心员工提离职?
最近一年互联网行情不好,很多大厂都在裁员,但裁员并不是不要人做事了。原来你这个岗位10个人做,企业有钱赚养得起,现在企业不怎么赚钱了,只能养4个人了。那么会有六个被裁掉。这时候对企业价值最大的4个人会被留下。也…...
建站系列(八)--- 本地开发环境搭建(WNMP)
目录 相关系列文章前言一、准备工作二、Nginx安装三、MySQL安装四、PHP安装及Nginx配置五、总结 相关系列文章 建站系列(一)— 网站基本常识 建站系列(二)— 域名、IP地址、URL、端口详解 建站系列(三)— …...
21天学会C++:Day8----范围for与nullptr
目录 编辑 1. 范围for 2. nullptr 1. 范围for 我们在写C语言循环遍历代码的时候,无论是用 for循环,while循环都需要考虑循环的起始条件,循环变量的递增逻辑,循环的结束条件。麻烦不说还可能会出错。 int main() {int arr[]…...
Linux——环境变量
✅<1>主页::我的代码爱吃辣 📃<2>知识讲解:Linux——环境变量 ☂️<3>开发环境:Centos7 💬<4>前言:环境变量(environment variables)一般是指在操作系统中用来指定操作…...
Screen的详细全面安装教程及Screen的用法
Screen可以大大提高终端使用效率,是Linux系统管理和运维的必备技能。当我们开启Screen后,只要Screen进程没有终止,其内部运行的会话都可以恢复。即使网络连接中断,用户也可以重新进入已开启的Screen中,对中断的会话进行…...
生成树、Prufer序列的计数问题:0912T1
看到生成树计数,很容易想到生成树计数 然后发现每个点有度数限制,我们可以先考虑枚举每个点的度数(也可以是Prufer 序列中的出现次数) 假设出现次数为 a a a,可以得出其生成树方案为 n ! ∏ ( a i − 1 ) ! \frac{…...
SQL_牛客网_SQL264_求每个登陆日期的次日留存率
牛客每个人最近的登录日期(五) 牛客每天有很多人登录,请你统计一下牛客每个日期新用户的次日留存率。 有一个登录(login)记录表,简况如下: id user_id client_id date 1 2 1 2020-10-12 2 3 2 2020-10-12 3 1 2 2020-10-…...
Hive 基础知识
目录 1.基础概念1.1 定义1.2 组件1.3 元数据1.4 内部表和外部表 2. Hive与关系型数据库的对比3. Hive 数据存储4. 参考文献 1.基础概念 1.1 定义 Hive是一个基于Hadoop的数据仓库基础设施工具,它可以将结构化的数据文件映射为一张数据库表,并提供类SQL查…...
【数据结构】树的基础知识及三种存储结构
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
