总结单例模式的写法

一、单例模式的概念

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.mzph.cn/news/871325.shtml

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

相关文章

基于php+mysql的简单图书管理系统(附源码)

一、模块设计 二、技术选型 IDE:phpstorm mysql:5.1 php:7.3.29 运行工具:phpstudy 三、数据库设计 用户表: CREATE TABLE t_user (id int(11) NOT NULL AUTO_INCREMENT,uname varchar(255) DEFAULT NULL,upass…

C语言的神髓

​​​​​​​ ​​​​​​​

记录些Redis题集(3)

分布式锁 分布式锁是一种用于在分布式系统中实现互斥访问的机制,它可以确保在多个节点、或进程同时访问共享资源。如果没有适当的锁机制,就可能导致数据不一致或并发冲突的问题。 分布式锁需要的介质 需要一个多个微服务节点都能访问的存储介质&#…

matine组件库踩坑日记 --- react

Mantine实践 一 禁忌核心css样式二 添加轮播图扩展组件 一 禁忌核心css样式 import React from react import ReactDOM from react-dom/client import { BrowserRouter } from react-router-dom; import App from ./App.jsx import ./index.css import mantine/core/styles.cs…

RocketMQ~架构了解

简介 RocketMQ 具有高性能、高可靠、高实时、分布式 的特点。它是一个采用 Java 语言开发的分布式的消息系统,由阿里巴巴团队开发,在 2016 年底贡献给 Apache,成为了 Apache 的一个顶级项目。 在阿里内部,RocketMQ 很好地服务了集…

DHCPv6 详情及其报文介绍 - 附配置案例及验证命令(Cisco)

DHCPv6 诞生的原因 IPv6 协议具有地址空间巨大的特点,但同时长达 128 比特的 IPv6 地址又要求高效合理的地址自动分配和管理策略。IPv6 无状态地址配置方式(RFC2462)是目前广泛采用的 IPv6 地址自动配置方式。配置了该协议的主机只需相邻设备…

红日靶场----(三)1.漏洞利用

上期已经信息收集阶段已经完成,接下来是漏洞利用。 靶场思路 通过信息收集得到两个吧靶场的思路 1、http://192.168.195.33/phpmyadmin/(数据库的管理界面) root/root 2、http://192.168.195.33/yxcms/index.php?radmin/index/login&am…

函数(实参以及形参)

实际参数(实参) 实际参数就是在调用函数时传递给函数的具体值。这些值可以是常量、变量、表达式或更复杂的数据结构。实参的值在函数被调用时传递给对应的形参,然后函数内部就可以使用这些值来执行相应的操作。 int main() {int a 0;int b …

一篇文章教你掌握——Pytorch深度学习实践基础

一篇文章教你掌握——Pytorch深度学习实践 1. Overview 概述1.1 Rule-based systems 基于规则的系统1.2 Classic machine learning 经典机器学习1.3 Representation learning 表征学习1.4 Brief history of neural networks 神经网络简史 2. 配置环境2.1 安装Anaconda2.2 创建虚…

奥利奥广告策略解析「扭一扭、舔一舔、泡一泡」广告为何深入人心?

作为一个多年的广告人,我认为奥利奥的「扭一扭、舔一舔、泡一泡」广告策略非常巧妙。今天可以从专业的角度来分析分析一下,大概应该有三大原因吧。 品牌识别度与记忆点: “扭一扭、舔一舔、泡一泡”这句广告语简洁易记,富有节奏…

网关、DHCP协议、ip地址、子网掩码简单介绍

参考文章:https://baike.baidu.com/item/%E7%BD%91%E5%85%B3/98992?frge_ala https://baike.baidu.com/item/DHCP%E6%9C%8D%E5%8A%A1%E5%99%A8/9956953?fromModulelemma_inlink https://blog.csdn.net/weixin_58783105/article/details/135041342 https://blog.cs…

TreeMap----源码分析

源码分析&#xff1a; 通过查看源码可以知道其实现以及继承。 public class TreeMap<K,V>extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, java.io.Serializable{} 在开头其定义了一些成员变量&#xff0c;在底层因为TreeMap是呈现红黑…

ZGC的流程图

GC标记过程 1、初始标记 扫描所有线程栈的根节点&#xff0c;然后再扫描根节点直接引用的对象并进行标记。这个阶段需要停顿所有的应用线程&#xff08;STW&#xff09;&#xff0c;但由于只扫描根对象直接引用的对象&#xff0c;所以停顿时间很短。停顿时间高度依赖根节点的数…

我的AI音乐梦:ChatGPT帮我做专辑

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;AI篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来ChatGPT帮我做音乐专辑 嘿&#xff0c;朋友们&#xff01; 想象一下&#xff0c;如果有个超级聪明的机器人能帮你写…

d3dcompiler_47.dll缺失怎么修复,一步步分析d3dcompiler_47.dll文件

d3dcompiler_47.dll缺失怎么修复&#xff1f;快速教大家解决出现d3dcompiler_47.dll问题的方法&#xff0c;一步步教大家快速有效的将丢失的d3dcompiler_47.dll如何修复。 一步步修复d3dcompiler_47.dll分析 1. 重新安装受影响的程序 如果是特定程序报告缺少d3dcompiler_47.d…

游戏缺失steam_api64.dll的多种解决方法,分享几种靠谱的方法

在使用电脑进行游戏的过程中&#xff0c;可能会出现“找不到steam_api.dll&#xff0c;无法继续执行代码”的提示&#xff0c;导致游戏无法正常运行。对于这样的情况&#xff0c;我们需要采取一定的措施进行修复。本文将为您提供相关的解决方案。 一、找不到steam_api.dll对电脑…

python-28-零基础自学python-json存数据、读数据,及程序合并

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版 知识点&#xff1a; import json引入、 try-except-else return def函数、打开文件、 练习内容&#xff1a; 练习10-11&#xff1a;喜欢的数 编写一个程序&#xff0c;提示用户输入喜欢的数&#xff…

【人工智能】knn算法

目录 一、对[1.0,1.1],[1.0,1.0],[0,0],[0,0.1],[0.1,0.1],[1.1,1.1]六个点用knn进行聚类&#xff0c;并显示。 1. 未调用KNN算法前&#xff0c;绿色为未知分类 2. 调用KNN算法 3. 运行结果 二、使用knn算法分类手写数字文件 1. 第一个temp的含义 2. 第二个temp的含义 …

【ARM】使用JasperGold和Cadence IFV科普

#工作记录# 原本希望使用CCI自带的验证脚本来验证修改过后的address map decoder&#xff0c;但是发现需要使用JasperGold或者Cadence家的IFV的工具&#xff0c;我们公司没有&#xff0c;只能搜搜资料做一下科普了解&#xff0c;希望以后能用到吧。这个虽然跟ARM没啥关系不过在…

基于神经网络的分类和预测

基于神经网络的分类和预测 一、基础知识&#xff08;一&#xff09;引言&#xff08;二&#xff09;神经网络的基本概念&#xff08;1&#xff09;神经网络&#xff08;2&#xff09;神经元&#xff08;3&#xff09;常用的激活函数&#xff08;非线性映射函数&#xff09;&…