总结单例模式的写法

一、单例模式的概念

1.1 单例模式的概念

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。就是当前进程确保一个类全局只有一个实例。

1.2  单例模式的优点

  • 单例模式在内存中只有一个实例,减少了内存开支
  • 单例模式只生成一个实例,所以减少了系统的性能开销
  • 单例模式可以避免对资源的多重占用
  • 单例模式可以在系统设置全局的访问点

1.3 单例模式的缺点

  • 单例模式一般没有接口,扩展很困难
  • 单例模式不利于测试
  • 单例模式与单一职责原则有冲突

1.4 使用场景

  • 要求生成唯一序列号的环境
  • 在整个项目中需要一个共享访问点或共享数据
  • 创建一个对象需要消耗的资源过多
  • 需要定义大量的静态常量和静态方法(如工具类)的环境

2.懒汉式

懒汉式,顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则直接返回,没有则新建。


2.1 懒汉式(加锁)


public class Singleton {private static Singleton instance;private Singleton() {}public synchronized static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

 这种把锁直接方法上的办法,所有的访问都需要获取锁,导致了资源的浪费。

2.2 懒汉式(双重校验锁)

public class Singleton{//volatile修饰,防止指令重排private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {//第一重校验,检查实例是否存在if (instance == null) {//同步块synchronized (Singleton.class) {//第二重校验,检查实例是否存在,如果不存在才真正创建实例if (instance == null) {instance = new Singleton();}}}return instance;}}

我们把synchronized加在了方法的内部,一般的访问是不加锁的,只有在instance==null的时候才加锁。

(1)为什么要双重校验?

如果不双重校验。

如果两个线程一起调用getInstance方法,并且都通过了第一次的判断instance==null,那么第一个线程获取了锁,然后实例化了instance,然后释放了锁,然后第二个线程得到了线程,然后马上也实例化了instance。这就不符合我们的单例要求了。

(2)为什么要用volatile 修饰 instance?

防止指令重排。

那这个重排指的是哪?指的是instance = new Singleton(),我们感觉是一步操作的实例化对象,实际上对于JVM指令,是分为三步的:

  • 分配内存空间
  • 初始化对象
  • 将对象指向刚分配的内存空间

有些编译器为为了性能优化,可能会把第二步和第三步进行重排序,顺序就成了:

  • 分配内存空间
  • 将对象指向刚分配的内存空间
  • 初始化对象

3. 饿汉式

饿汉式,就像它的名字,饥不择食,定义的时候直接初始化。

public class Singleton{private static Singleton instance=new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}}

因为instance是个静态变量,所以它会在类加载的时候完成实例化,不存在线程安全的问题。

这种方式不是懒加载,不管我们的程序会不会用到,它都会在程序启动之初进行初始化。

4. 静态内部类

静态内部类是更进一步的写法,不仅能实现懒加载、线程安全,而且JVM还保持了指令优化的能力。

public class Singleton{private Singleton() {}private static class InnerSingleton {private static final Singleton instance = new Singleton();}public static Singleton getInstance() {return InnerSingleton.instance;}
}

Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会加载静态内部类InnerSingleton类,从而完成Singleton的实例化。

类的静态属性只会在第一次加载类的时候初始化,同时类加载的过程又是线程互斥的,JVM帮助我们保证了线程安全。

5. 枚举

通过enum修饰Singleton单例类,仅需定义一个INSTANCE,然后在静态方法实例化方法getInstance中直接返回INSTANCE即可。

public enum Singleton {INSTANCE;public static Singleton getInstance(){return INSTANCE;}
}

6 总结


饿汉模式:线程是安全的,只进行读操作
懒汉模式:不安全,有读操作也有写操作

单例模式的选择取决于具体需求,如是否需要懒加载、是否需要线程安全等。每种实现方式都有其适用场景和潜在问题,设计时应根据具体情况选择最合适的实现方法。

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

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

相关文章

2024 China Joy 前瞻 | 腾讯网易发新作,网易数智携游戏前沿科技、创新产品以及独家礼盒,精彩不断!

今年上半年,CES、MWC和AWE三大国际科技展轮番轰炸,吸引全球科技爱好者的高度关注,无论是新潮的科技产品,还是对人工智能的探索,每一项展出的技术和产品都引起了市场的热议。而到了下半年,一年一度的China J…

Kafka消息队列python开发环境搭建

目录 引言 Kafka 的核心概念和组件 Kafka 的主要特性 使用场景 申请云服务器 安装docker及docker-compose VSCODE配置 开发环境搭建 搭建Kafka的python编程环境 Kafka的python编程示例 引言 Apache Kafka 是一个分布式流处理平台,由 LinkedIn 开发并在 2…

Android View的绘制流程

1.不管是View的添加,还是调用View的刷新方法invalidate()或者requestLayout(),绘制都是从ViewRootImpl的scheduleTraversals()方法开始 void scheduleTraversals() {if (!mTraversalScheduled) {mTraversalScheduled true;mTraversalBarrier mHandler…

SpringCloud教程 | 第九篇: 使用API Gateway

1、参考资料 SpringCloud基础篇-10-服务网关-Gateway_springcloud gateway-CSDN博客 2、先学习路由,参考了5.1 2.1、建了一个cloudGatewayDemo,这是用来配置网关的工程,配置如下: http://localhost:18080/aaa/name 该接口代码如…

科普文:详解23种设计模式

概叙 设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four(GoF)的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分别为创建型模式…

等保-Linux等保测评

等保-Linux等保测评 1.查看相应文件,账户xiaoming的密码设定多久过期 rootdengbap:~# chage -l xiaoming Last password change : password must be changed Password expires : pass…

理解类与对象:面向对象基础

目录 1. 类的定义1.1 格式1.2 访问限定符1.3 类域 2.实例化2.1 实例化概念2.2 对象大小 3.this指针 1. 类的定义 1.1 格式 class为定义类的关键字,Date为类的名字,{ }中为类的主体,注意类定义结束后面的分号不能省略。类体中内容称为类的成…

【博士每天一篇文献-算法】连续学习算法之HNet:Continual learning with hypernetworks

阅读时间:2023-12-26 1 介绍 年份:2019 作者:Johannes von Oswald,Google Research;Christian Henning,EthonAI AG;Benjamin F. Grewe,苏黎世联邦理工学院神经信息学研究所 期刊&a…

如何在项目中打印sql和执行的时间

目标:打印DAO方法中sql和执行的时间 一种方式是去实现Mybatis的拦截器Interceptor ,比较麻烦; 这里介绍一种比较简单的实现方式; 1、如何打印sql? 配置文件加这个可以打印出com.zhenhui.ids.busi.watch包下执行的sq…

3D线上展厅:元宇宙时代的营销利器,流量暴增的秘密武器!

在体验经济蓬勃发展的当下,企业营销领域正以前所未有的热情探索创新路径,元宇宙这一融合了无限想象与未来科技的概念,成为了众多品牌竞相追逐的新蓝海。3D技术、增强现实(AR)、虚拟现实(VR)以及…

【ProtoBuf】proto 3 语法 -- 详解

这个部分会对通讯录进行多次升级,使用 2.x 表示升级的版本,最终将会升级如下内容: 不再打印联系人的序列化结果,而是将通讯录序列化后并写入文件中。 从文件中将通讯录解析出来,并进行打印。 新增联系人属性&#xff…

谈谈大数据采集和常见问题

01 什么是数据采集 数据采集是大数据的基石,不论是现在的互联网公司,物联网公司或者传统的IT公司,每个业务流程环节都会产生大量的数据,同时用户操作的日志也会产生大量的数据,为了将这些结构化和非结构化的数据进行…

【常见开源库的二次开发】基于openssl的加密与解密——单向散列函数(四)

目录: 目录: 一、什么是单项散列函数? 1.1 如何验证文件是否被修改过 1.2 单项散列函数: 二、单向hash抗碰撞 2.1 弱抗碰撞(Weak Collision Resistance) 2.2 强抗碰撞(Strong Collision Resista…

Webpack详解

Webpack Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。它允许开发者将项目中的资源(如 JavaScript、CSS、图片等)视为模块,通过分析和处理这些模块之间的依赖关系,将它们打包…

Python酷库之旅-第三方库Pandas(024)

目录 一、用法精讲 61、pandas.to_numeric函数 61-1、语法 61-2、参数 61-3、功能 61-4、返回值 61-5、说明 61-6、用法 61-6-1、数据准备 61-6-2、代码示例 61-6-3、结果输出 62、pandas.to_datetime函数 62-1、语法 62-2、参数 62-3、功能 62-4、返回值 62-…

ospf的MGRE实验

第一步:配IP [R1-GigabitEthernet0/0/0]ip address 12.0.0.1 24 [R1-GigabitEthernet0/0/1]ip address 21.0.0.1 24 [R1-LoopBack0]ip address 192.168.1.1 24 [ISP-GigabitEthernet0/0/0]ip address 12.0.0.2 24 [ISP-GigabitEthernet0/0/1]ip address 21.0.0.2 24…

Hadoop3:HDFS-存储优化之纠删码

一、集群环境 集群一共5个节点,102/103/104/105/106 二、纠删码原理 1、简介 HDFS默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。Hadoop3.x引入了纠删码,采用计算的方式&#x…

新一代大语言模型 GPT-5 对工作与生活的影响及应对策略

文章目录 📒一、引言 📒二、GPT-5 的发展背景 🚀(一)GPT-4 的表现与特点 🚀(二)GPT-5 的预期进步 📒三、GPT-5 对工作的影响 🚀(一&#xf…

交叉编译ethtool(ubuntu 2018)

参考文章:https://www.cnblogs.com/nazhen/p/16800427.html https://blog.csdn.net/weixin_43128044/article/details/137953913 1、下载相关安装包 //ethtool依赖libmul git clone http://git.netfilter.org/libmnl //ethtool源码 git clone http://git.kernel.or…

OpenGL笔记十三之Uniform向量数据传输、使用glUniform3f和glUniform3fv

OpenGL笔记十三之Uniform向量数据传输、使用glUniform3f和glUniform3fv —— 2024-07-14 晚上 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记十三之Uniform向量数据传输、使用glUniform3f和glUniform3fv1.glUniform3f1.1.运行1.2.vs1.3.fs1.4.shader.…