单例模式的八种写法、单例和并发的关系

文章目录

  • 1.单例模式的作用
  • 2.单例模式的适用场景
  • 3.饿汉式
    • 静态常量(可用)
    • 静态代码块(可用)
  • 4.懒汉式
    • 线程不安全(不可用)
    • 同步方法(线程安全,但不推荐用)
    • 同步代码块(线程不安全,不可用)
    • 双重检查 + volatile(推荐用)
    • 静态内部类(推荐用)
    • 枚举(推荐用)

1.单例模式的作用

为什么需要单例?

  • 节省内存和计算
  • 保证结果正确
  • 方便管理

2.单例模式的适用场景

  1. 无状态的工具类:比如日志工具类,不管是在哪里使用,我们需要的只是它帮我们记录日志信息,除此之外,并不需要在它的实例对象上存储任何状态,这时候我们就只需要一个实例对象即可。
  2. 全局信息类:比如我们在一个类上记录网站的访问次数,我们不希望有的访问被记录在对象 A 上,有的却记录在对象 B 上,这时候我们就让这个类成为单例。

3.饿汉式

静态常量(可用)

/*** 饿汉式(静态常量)(可用)*/
public class Singleton1 {// 由于加了static关键字,根据JVM的规定,在类加载的时候就会完成INSTANCE的实例化,这样就避免了线程同步问题private final static Singleton1 INSTANCE = new Singleton1();// 构造函数是私有的private Singleton1() {}public static Singleton1 getInstance() {return INSTANCE;}
}

静态代码块(可用)

/*** 饿汉式(静态代码块)(可用)*/
public class Singleton2 {private final static Singleton2 INSTANCE;// 与上一种写法类似,由JVM保证了线程安全static {INSTANCE = new Singleton2();}// 构造函数是私有的private Singleton2() {}public static Singleton2 getInstance() {return INSTANCE;}
}

4.懒汉式

线程不安全(不可用)

/*** 懒汉式(线程不安全)(不可用)*/
public class Singleton3 {private static Singleton3 instance;// 构造函数是私有的private Singleton3() {}public static Singleton3 getInstance() {// 这种写法是线程不安全的,不可用if (instance == null) {instance = new Singleton3();}return instance;}
}

同步方法(线程安全,但不推荐用)

/*** 懒汉式(线程安全)(不推荐用)*/
public class Singleton4 {private static Singleton4 instance;// 构造函数是私有的private Singleton4() {}// 这种写法虽然是线程安全的,但是效率太低,不推荐用public synchronized static Singleton4 getInstance() {if (instance == null) {instance = new Singleton4();}return instance;}
}

同步代码块(线程不安全,不可用)

/*** 懒汉式(线程不安全)(不可用)*/
public class Singleton5 {private static Singleton5 instance;// 构造函数是私有的private Singleton5() {}public static Singleton5 getInstance() {// 这种写法并不是线程安全的,不可用if (instance == null) {synchronized (Singleton5.class) {instance = new Singleton5();}}return instance;}
}

双重检查 + volatile(推荐用)

优点:线程安全,延迟加载,效率较高。

/*** 双重检查 + volatile(推荐用)*/
public class Singleton6 {// volatile防止重排序private volatile static Singleton6 instance;// 构造函数是私有的private Singleton6() {}public static Singleton6 getInstance() {// 双重检查保证线程安全if (instance == null) {synchronized (Singleton6.class) {if (instance == null) {instance = new Singleton6();}}}return instance;}
}

为什么要用 volatile?

新建对象 rs = new Resource() 实际上有 3 个步骤:

  • construct empty resource()
  • call constructor
  • assign to rs

如下图所示,重排序会带来NPE问题(NullPointerException, 空指针异常),而使用 volatile 可以防止重排序。

在这里插入图片描述

静态内部类(推荐用)

/*** 静态内部类(线程安全,懒加载)(推荐用)*/
public class Singleton7 {// 构造函数是私有的private Singleton7() {}// 由JVM的规定可知,这种写法同时满足了线程安全和懒加载两个优点private static class SingletonInstance {private static final Singleton7 INSTANCE = new Singleton7();}public static Singleton7 getInstance() {return SingletonInstance.INSTANCE;}
}

枚举(推荐用)

单例模式的书写:

/*** 枚举(线程安全,懒加载)(推荐用)*/
public enum Singleton8 {INSTANCE;public void whatever() {}
}

单例的使用:

Singleton8.INSTANCE.whatever();

哪种单例的实现方案最好?

Joshua Bloch 大神在《Effective Java》中明确表达过的观点:使用枚举实现单例的方法虽然还没有广泛采用,但是单元素的枚举类型已经成为实现 Singleton 的最佳方法。

  • 写法简单
  • 线程安全有保障
  • 懒加载
  • 避免反序列化破坏单例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/237140.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于PhpStorm的安装激活与汉化

访问官网下载PhpStorm https://www.jetbrains.com/phpstorm/download/#sectionwindows 点击download 下载好后,双击exe安装程序 点击下一步 选择安装位置 前两个肯定需要勾选: 创建桌面快捷方式;创建关联php; 根据以往经验&am…

canvasdrawer 微信原生小程序生成海报图片

在小程序中生成海报是一种非常有效的推广方式 用户可以使用小程序的过程中生成小程序海报并分享给他人 通过海报的形式,用户可以直观地了解产品或服务的特点和优势 常见绘制海报方式 目前,小程序海报有两种常见的实现方式: canvas 绘制…

LTESniffer:一款功能强大的LTE上下行链路安全监控工具

关于LTESniffer LTESniffer是一款功能强大的LTE上下行链路安全监控工具,该工具是一款针对LTE的安全开源工具。 该工具首先可以解码物理下行控制信道(PDCCH)并获取所有活动用户的下行链路控制信息(DCI)和无线网络临时…

【iOS】数据持久化(四)之FMDB基本使用

正如我们前面所看到的,原生SQLite API在使用时还是比较麻烦的,于是,开源社区就出现了一系列将SQLite API进行封装的库,其中FMDB的被大多数人所使用 FMDB和SQLite相比较,SQLite比较原始,操作比较复杂&#…

POI:对Word的基本操作

1 向word中写入文本并设置样式 package com.example;import org.apache.poi.xwpf.usermodel.*;import java.io.File; import java.io.FileOutputStream;/*** Author:xiexu* Date:2024/1/12 23:54*/ public class WriteWord {static String PATH "…

数据库:如何取消mysql的密码

因为调试MySQL数据接口,总是需要输入密码很烦,所以决定取消mysql的root密码, 网上推荐的有两种方法: 1、mysql命令 SET PASSWORD FOR rootlocalhostPASSWORD(); 2、运行 mysqladmin 命令 mysqladmin -u root -p password …

逼格满满,推荐一个高效测试用例工具:XMind2TestCase !

一、背景 软件测试的核心是什么?毫无疑问是测试分析和测试用例设计,也是日常测试投入最多时间的工作内容之一。 然而,传统的测试用例设计过程有很多痛点: 1、使用Excel表格进行测试用例设计,虽然成本低,但…

MaxKey 单点登录认证系统——实现登录后自动跳转及分析思路

Maxkey单点登录系统集成业务系统应用之后,登录界面登录之后不会自动跳转业务系统,需要在首页点击相应应用之后,才能实现跳转业务系统,故以下本人提供解决方法和分析思路。 环境配置 本例使用的是CAS协议实现单点登录 Maxkey 服务…

Golang的API项目快速开始

开启一个简单的API服务。 golang的教程网上一大堆,官网也有非常详细的教程,这里不在赘述这些基础语法教程,我们意在快速进入项目开发阶段。 golang好用语法教程传送门: m.runoob.com/go/ 编写第一个API 前提:按照上一…

麒麟操作系统缓存rpm包,制作离线yum源

缓存rpm包,以make为例 mkdir -p /data/yum yumdownloader --resolve --destdir/data/yum make制作离线yum包 yum install createrepo -y cd /data/yum createrepo .写yum配置文件/etc/yum.repos.d/local.repo [local-repo] namelocal-repo baseurlfile:///data/…

python_selenium零基础爬虫学习案例_知网文献信息

案例最终效果说明: 去做这个案例的话是因为看到那个博主的分享,最后通过努力,我基本实现了进行主题、关键词、更新时间的三个筛选条件去获取数据,并且遍历数据将其导出到一个CSV文件中,代码是很简单的,没有…

JUC之CompletableFuture

Future接口理论 Future接口定义了异步任务执行的一些方法&#xff0c;包括异步任务执行结果&#xff0c;异步任务执行是否中断&#xff0c;异步任务是否完毕等。 Future接口常用实现类FutureTask异步任务 FutureTask<String> futureTask new FutureTask<String>…

debian12部署Gitea服务之二——部署git-lfs

Debian安装gitlfs: 先更新下软件包版本 sudo apt update 安装 sudo apt install git-lfs 验证是否安装成功 git lfs version cd到Gitea仓库目录下 cd /mnt/HuHDD/Git/Gitea/Repo/hu/testrepo.git 执行lfs的初始化命令 git lfs install客户机Windows端在官网下载并安装Git-Lfs 再…

Elasticsearch windows开箱即用【记录】

一、准备工作 安装ES之前要在本机安装好JDK&#xff0c;对应的兼容性见官网链接&#xff1a;https://www.elastic.co/cn/support/matrix ES官网链接&#xff1a;https://www.elastic.co/cn/, 我本机安装的是JDK8&#xff0c;测试使用的是7.3.0版本的ES和Kibana。 1、首先去…

iOS Universal Links(通用链接)详细教程

一&#xff1a;Universal Links是用来做什么的&#xff1f; iOS9.0推出的用于应用之间跳转的一种机&#xff0c; 通过一个https的链接启动app。如果手机有安装需要启动的app&#xff0c;可实现无缝跳转。如果没有安装&#xff0c;会打开网页。 实现场景&#xff1a;微信链接无…

Linux中快速搭建RocketMQ测试环境

必要的文件下载 为什么选择RocketMQ | RocketMQ x86_64位JDK下载0jdk/8u391-b13 rocketmq二进制包下载-rocketmq-all-5.1.4-bin-release.zip 编译好的直接可用的dashboard【rocketmq-dashboard-1.0.0.jar】请在文章顶部下载 dashboard配套的配置文件【application.propert…

【2024系统架构设计】 系统架构设计师第二版-通信系统架构设计理论与实践

目录 一 通信系统网络架构 二 网络构建的关键技术 三 网络构建和设计方法 四 案例分析 注:本节内容可作为知识储备,做一个基本的了解即可。

qt-C++笔记之QProcess

qt-C笔记之QProcess code review! 文章目录 qt-C笔记之QProcess零.示例&#xff1a;QProcess来执行不带参数的系统命令ls并打印出结果一.示例&#xff1a;QProcess来执行系统命令ls -l命令并打印出结果说明 二.示例&#xff1a;QProcess来执行系统命令ls -l命令并打印出结果&…

Android14实战:打破音频默认重采样的限制(五十二)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

spark中Rdd依赖和SparkSQL介绍--学习笔记

1&#xff0c;RDD的依赖 1.1概念 rdd的特性之一 相邻rdd之间存在依赖关系&#xff08;因果关系&#xff09; 窄依赖 每个父RDD的一个Partition最多被子RDD的一个Partition所使用 父rdd和子rdd的分区是一对一&#xff08;多对一&#xff09; 触发窄依赖的算子 map()&…