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

八种单例模式

文章目录

    • 1.单例模式基本介绍
        • 1.介绍
        • 2.单例模式八种方式
    • 2.饿汉式(静态常量,推荐)
        • 1.基本步骤
          • 1.构造器私有化(防止new)
          • 2.类的内部创建对象
          • 3.向外暴露一个静态的公共方法
        • 2.代码实现
        • 3.优缺点分析
    • 3.饿汉式(静态代码块,推荐)
        • 1.代码实现
        • 2.优缺点分析
    • 4.懒汉式(线程不安全,实际开发不要使用)
        • 1.代码实现
        • 2.优缺点分析
    • 5.懒汉式(线程安全,同步方法,实际开发不推荐使用)
        • 1.代码实现
        • 2.优缺点分析
    • 6.懒汉式(线程安全,同步代码块,解决不了同步问题)
        • 1.介绍
        • 2.优缺点分析
    • 7.双重检查(推荐使用)
        • 1.代码实现
        • 2.关于volatile关键字
          • 使用 `volatile` 的常见场景
          • 复合操作的限制
          • 总结
        • 3.优点分析
    • 8.静态内部类实现(推荐使用)
        • 1.前置知识
          • 1.外部类被装载,静态内部类不会被装载
          • 2.当调用静态内部类的属性时,静态内部类会被装载且只会被装载一次
          • 3.在类装载的时候是线程安全的
        • 2.代码实现
        • 3.优点分析
    • 9.枚举实现(推荐使用)
        • 1.代码实现
        • 2.优缺点分析
    • 10.单例模式总结
        • 1.Runtime就使用了饿汉式的单例模式
        • 2.注意事项和细节

1.单例模式基本介绍

1.介绍

image-20240526192046799

2.单例模式八种方式

image-20240526192132094

2.饿汉式(静态常量,推荐)

1.基本步骤
1.构造器私有化(防止new)
2.类的内部创建对象
3.向外暴露一个静态的公共方法
2.代码实现
package com.sun.type1;/*** Description: 单例模式饿汉式(静态变量)* @Author sun* @Create 2024/5/26 19:28* @Version 1.0*/
public class Singleton01 {public static void main(String[] args) {// 通过公有的静态方法,获取实例Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance1 == instance); // 返回的是true}
}class Singleton {// 1.构造器私有化private Singleton() {}// 2.本类的内部创建对象实例private final static Singleton instance = new Singleton();// 3.暴露一个公有的静态方法,返回实例对象public static Singleton getInstance() {return instance;}
}

image-20240526194327006

3.优缺点分析

image-20240526194535444

3.饿汉式(静态代码块,推荐)

1.代码实现
package com.sun.type1;/*** Description: 单例模式饿汉式(静态代码块)* @Author sun* @Create 2024/5/26 19:49* @Version 1.0*/
public class Singleton02Test {public static void main(String[] args) {// 通过公有的静态方法,获取实例Singleton02 instance = Singleton02.getInstance();Singleton02 instance1 = Singleton02.getInstance();System.out.println(instance1 == instance); // 返回的是true}
}class Singleton02 {// 1.构造器私有化private Singleton02() {}// 2.本类的内部有一个静态属性private static Singleton02 instance;// 3.使用静态代码块为静态属性初始化static {instance = new Singleton02();}// 4.暴露一个公有的静态方法,返回实例对象public static Singleton02 getInstance() {return instance;}
}
2.优缺点分析

image-20240526200000545

4.懒汉式(线程不安全,实际开发不要使用)

1.代码实现
package com.sun.type3;/*** Description: 单例模式懒汉式(线程不安全)* @Author sun* @Create 2024/5/26 20:02* @Version 1.0*/
public class Singleton03Test {public static void main(String[] args) {Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance1 == instance);}
}class Singleton {// 1.构造器私有化private Singleton() {}// 2.静态属性,存放本类对象private static Singleton instance;// 3.静态的公有方法,当使用到该方法时才会去创建instancepublic static Singleton getInstance() {// 当静态属性没有被赋值的时候再去创建if (instance == null) {instance = new Singleton();}// 如果这个静态属性被初始化过了,就直接返回,保证是单例的return instance;}
}
2.优缺点分析

image-20240526201118772

5.懒汉式(线程安全,同步方法,实际开发不推荐使用)

1.代码实现
package com.sun.type4;/*** Description: 单例模式懒汉式(线程安全,同步方法)* @Author sun* @Create 2024/5/26 20:15* @Version 1.0*/
public class Singleton04Test {public static void main(String[] args) {Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance1 == instance);}
}class Singleton {// 1.构造器私有化private Singleton() {}// 2.静态属性,存放本类对象private static Singleton instance;// 3.静态的公有方法,当使用到该方法时才会去创建instance,使用synchronized实现线程安全public static synchronized Singleton getInstance() {// 当静态属性没有被赋值的时候再去创建if (instance == null) {instance = new Singleton();}// 如果这个静态属性被初始化过了,就直接返回,保证是单例的return instance;}
}
2.优缺点分析

image-20240526202034683

6.懒汉式(线程安全,同步代码块,解决不了同步问题)

1.介绍

image-20240526202352115

2.优缺点分析

image-20240526202512379

7.双重检查(推荐使用)

1.代码实现
package com.sun.type6;/*** Description: 双重检查* @Author sun* @Create 2024/5/26 20:15* @Version 1.0*/
public class Singleton06Test {public static void main(String[] args) {Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance1 == instance);}
}class Singleton {// 1.构造器私有化private Singleton() {}// 2.静态属性,存放本类对象,使用volatile防止指令重排序private static volatile Singleton instance;// 3.静态的公有方法,当使用到该方法时才会去创建instancepublic static Singleton getInstance() {// 先检查一次静态属性是否为空,这样可以过滤掉一部分if (instance == null) {// 如果为空,则进入同步代码块创建对象,由于还是会有多个线程进来,所以在内部需要二次检查synchronized (Singleton.class) {// 在此完成双重检查if (instance == null) {instance = new Singleton();}}}// 如果这个静态属性被初始化过了,就直接返回,保证是单例的return instance;}
}
2.关于volatile关键字
使用 volatile 的常见场景
  1. 直接赋值

    • 设置标志位,如控制线程的开始或停止。
    • 单个配置值的更新,这个值被多个线程读取。

    例如,一个线程控制开关:

    public class TaskRunner implements Runnable {private volatile boolean stop = false;public void run() {while (!stop) {// 执行任务}}public void stop() {stop = true;}
    }
    
  2. 单一读取操作

    • 在这种情况下,volatile 保证了每次读取操作都从主内存中获取最新值,而不是从线程的本地缓存。
复合操作的限制

如果操作涉及到对变量的读取、修改和写回(如 a++),则 volatile 不能保证操作的原子性。这类操作需要使用 synchronizedjava.util.concurrent.atomic 包中的原子类。例如,对一个计数器进行增加操作:

public class Counter {private volatile int count = 0; // 这是错误的做法,对于 count++ 操作public void increment() {count++; // 这不是线程安全的}
}

在上面的代码中,count++ 操作实际上是三个步骤:读取 count 的当前值,增加 1,然后写回新值。这三个步骤不是原子操作,因此即使 count 被声明为 volatile,在多线程环境中也可能导致不正确的结果。

总结

总之,当你的需求仅限于确保多线程之间对单个变量直接赋值操作的可见性和有序性时,使用 volatile 是合适的。然而,对于需要多个步骤或基于当前值的修改的操作,你需要使用更强的同步机制。

3.优点分析

image-20240526204442702

8.静态内部类实现(推荐使用)

1.前置知识
1.外部类被装载,静态内部类不会被装载
2.当调用静态内部类的属性时,静态内部类会被装载且只会被装载一次
3.在类装载的时候是线程安全的
2.代码实现
package com.sun.type7;/*** Description: 单例模式(静态内部类实现)* @Author sun* @Create 2024/5/26 20:51* @Version 1.0*/
public class Singleton07Test {public static void main(String[] args) {Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance1 == instance);}
}class Singleton {// 1.构造器私有化private Singleton() {}// 2.一个静态内部类,该类有一个静态属性,存放外部类的对象private static class SingletonInstance {public static final Singleton INSTANCE = new Singleton();}// 3.静态的公有方法,当要使用时调用内部类的静态属性,此时静态内部类会被装载,且只会被装载一次public static Singleton getInstance() {return SingletonInstance.INSTANCE;}
}
3.优点分析

image-20240526210255702

9.枚举实现(推荐使用)

1.代码实现
package com.sun.type8;/*** Description: 单例模式(静态内部类实现)* @Author sun* @Create 2024/5/26 20:51* @Version 1.0*/
public class Singleton08Test {public static void main(String[] args) {Singleton instance = Singleton.INSTANCE;Singleton instance2 = Singleton.INSTANCE;System.out.println(instance2 == instance);}
}enum Singleton {// 这个就相当于调用无参构造创建了这个类的一个对象,可以实现单例模式INSTANCE;
}
2.优缺点分析

image-20240526210742011

10.单例模式总结

1.Runtime就使用了饿汉式的单例模式

image-20240526211234759

2.注意事项和细节

image-20240526211508150

相关文章:

八种单例模式

文章目录 1.单例模式基本介绍1.介绍2.单例模式八种方式 2.饿汉式(静态常量,推荐)1.基本步骤1.构造器私有化(防止new)2.类的内部创建对象3.向外暴露一个静态的公共方法 2.代码实现3.优缺点分析 3.饿汉式(静态…...

禅道密码正确但是登录异常处理

禅道密码正确,但是登录提示密码错误的异常处理 排查内容 # 1、服务器异常,存储空间、数据库异常 # 2、服务异常,文件丢失等异常问题定位 # 1、df -h 排查服务器存储空间 # 2、根据my.php排查数据库连接是否正常 # 3、修改my.pho,debugtrue…...

Go微服务: Nacos的搭建和基础API的使用

Nacos 概述 文档:https://nacos.io/docs/latest/what-is-nacos/搭建:https://nacos.io/docs/latest/quickstart/quick-start-docker/有很多种搭建方式,我们这里使用 docker 来搭建 Nacos 的搭建 这里,我们选择单机模式&#xf…...

基于Hadoop的城市公共交通大数据时空分析

基于Hadoop的城市公共交通大数据时空分析 “Spatio-temporal Analysis of Urban Public Transportation Big Data based on Hadoop” 完整下载链接:基于Hadoop的城市公共交通大数据时空分析 文章目录 基于Hadoop的城市公共交通大数据时空分析摘要第一章 引言1.1 研究背景1.2 …...

DNS服务的部署与配置(2)

1、dns的安装及开启 dnf install bind.x86_64 -y #安装 #Berkeley Internet Name Domain (BIND) systemctl enable --now named #启用dns服务,服务名称叫named firewall-cmd --permanent --add-servicedns #火墙设置 firewall-cmd --reload …...

MySql--SQL语言

目录 SQl---DDL 结构定义 创建、删除 数据库 代码 运行 设计表 数据类型 整数 浮点数 主键 约束 主键自增长 默认值 字段注释 创建、删除 表 代码 运行 代码 代码 运行 SQL---DML 数据操纵 插入数据 代码 运行 代码 运行 代码 运行 代码 …...

【网络安全】2030年十大新兴网络安全威胁

欧盟网络安全局(ENISA)已发布了一份全面的清单,列出了预计到2030年将影响数字领域的十大新兴网络安全威胁。 该预测是为期八个月的广泛研究的成果,融合了ENISA前瞻专家小组、CSIRTs网络以及欧盟CyCLONe专家的见解。 这项研究突显…...

python数据分析-CO2排放分析

导入所需要的package import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import datetime %matplotlib inline plt.rcParams[font.sans-serif] [KaiTi] #中文 plt.rcParams[axes.unicode_minus] False #负号 数据清洗…...

2024宝藏工具EasyRecovery数据恢复软件免费版本下载

在这个数字化的时代,数据已经成为我们生活中的重中之重。无论是工作中的重要文件,还是手机中珍贵的照片,我们都依赖着这些数据。然而,数据丢失的情况时有发生,可能是误删,可能是设备故障,更可能…...

【EventSource错误解决方案】设置Proxy后SSE发送的数据只在最后接收到一次,并且数据被合并

【EventSource错误解决方案】设置Proxy后SSE发送的数据只在最后接收到一次,并且数据被合并 出错描述 出错原因与解决方案 出错描述 SSE前后端一切正常,但是fetchEventSource 的onmessage回调函数只在所有流都发送完毕后,才会执行一次。 前…...

如何在linux命令行(终端)执行ipynb 文件。可以不依赖jupyter

1.安装 runipy pip install runipy 2.终端运行 runipy <YourNotebookName>.ipynb 在终端命令行执行shell脚本&#xff0c;&#xff08;也可以在crontab 中执行&#xff09;&#xff1a; (base) [recommendapp-0-5-B-006 script]$ cat run1.sh #!/bin/bashcd /home/recom…...

基于YOLOv8的车牌检测与识别(CCPD2020数据集)

前言 本篇博客主要记录在autodl服务器中基于yolov8实现车牌检测与识别&#xff0c;以下记录实现全过程~ yolov8源码&#xff1a;GitHub - ultralytics/ultralytics: NEW - YOLOv8 &#x1f680; in PyTorch > ONNX > OpenVINO > CoreML > TFLite 一、环境配置 …...

驱动开发之新字符设备驱动开发

1.前言 register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数&#xff0c;现在新的 字符设备驱动已经不再使用这两个函数&#xff0c;而是使用 Linux 内核推荐的新字符设备驱动 API 函数。 旧版本的接口使用&#xff0c;感兴趣可以看下面这个博客&#…...

【JMU】21编译原理期末笔记

本拖延症晚期患者不知不觉已经有半年没写博客了&#xff0c;天天不知道在忙什么。 乘着期末周前赶紧先把编译原理上传了&#xff0c;我记得我这科是86分&#xff0c;有点小遗憾没上90&#xff0c;但是总体不错。 链接&#xff1a;https://pan.baidu.com/s/1gO8pT7paHv1lkM_ZpkI…...

就业信息|基于SprinBoot+vue的就业信息管理系统(源码+数据库+文档)

就业信息管理系统 目录 基于SprinBootvue的就业信息管理系统 一、前言 二、系统设计 三、系统功能设计 1前台功能模块 2后台功能模块 4.2.1管理员功能 4.2.2学生功能 4.2.3企业功能 4.2.4导师功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设…...

一.架构设计

架构采用 ddd 架构&#xff0c;不同于传统简单的三层的架构&#xff0c;其分层的思想对于大家日后都是很有好处的&#xff0c;会给大家的思想层级&#xff0c;提高很多。 传统的项目 现有的架构 采取ddd架构&#xff0c;给大家在复杂基础上简化保留精髓&#xff0c;一步步进行…...

<学习笔记>从零开始自学Python-之-实用库篇(一)-pyscript

由Anaconda创建的PyScript是一项实验性的但很有前途的新技术&#xff0c;它使python运转时在支撑WebAssembly的浏览器中作为一种脚本言语运用。 每个现代常用的浏览器现在都支撑WebAssembly&#xff0c;这是许多言语&#xff08;如C、C和Rust&#xff09;能够编译的高速运转时…...

Vue项目中npm run build 卡住不执行的几种情况(实战版)

方法一 一&#xff1a;比较常见是镜像导致的原因 我们可以找到build/check-versions文件 将这段代码注释,重新运行就可以解决这个问题 if (shell.which(npm)) {versionRequirements.push({name: npm,currentVersion: exec(npm --version),versionRequirement: packageConfig.en…...

《Python源码剖析》之pyc文件

前言 前面我们主要围绕pyObject和pyTypeObject聊完了python的内建对象部分&#xff0c;现在我们将开启新的篇章—python虚拟机&#xff0c;将聚焦在python的执行部分&#xff0c;搞懂从“代码”到“执行”的过程。开启新的篇章之前&#xff0c;你也许会有一个疑惑&#xff1a;我…...

Python零基础-中【详细】

接上篇继续&#xff1a; Python零基础-上【详细】-CSDN博客 目录 十、函数式编程 1、匿名函数lambda表达式 &#xff08;1&#xff09;匿名函数理解 &#xff08;2&#xff09;lambda表达式的基本格式 &#xff08;3&#xff09;lambda表达式的使用场景 &#xff08;4&…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...