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

总结单例模式的写法

一、单例模式的概念

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 总结


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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 掌握Python异步编程:一步一步迈向高效网络应用开发
  • centos7安装mysql-8.0.38-1.el7.x86_64.rpm-bundle.tar
  • 无人机航电系统技术详解
  • 【人工智能】-- 受限玻尔兹曼机
  • nginx代理gitee
  • 工控主板:搭载海光3300处理器的全国产化工控主板
  • nginx代理缓存
  • nx上darknet的使用-目标检测-在python中的使用
  • Nextjs 调用组件内的方法
  • Hypertable install of rhel6.0
  • CCRC-DSA数据安全评估师: 数据安全治理不仅是技术革新更是理念变革
  • axios 下载大文件时,展示下载进度的组件封装——js技能提升
  • 算法金 | 来了,pandas 2.0
  • vue2 ant-design select组件自定义下拉框, dropdownRender 使用,以及遇到的坑
  • fastadmin 如何通过权限组来控制列的显示与隐藏
  • [ JavaScript ] 数据结构与算法 —— 链表
  • Consul Config 使用Git做版本控制的实现
  • dva中组件的懒加载
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 编写符合Python风格的对象
  • 测试开发系类之接口自动化测试
  • 基于web的全景—— Pannellum小试
  • 前端学习笔记之观察者模式
  • 新书推荐|Windows黑客编程技术详解
  • 运行时添加log4j2的appender
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • 浅谈sql中的in与not in,exists与not exists的区别
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • (4)logging(日志模块)
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (五)关系数据库标准语言SQL
  • (一) storm的集群安装与配置
  • (一)Docker基本介绍
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (转)http协议
  • **CI中自动类加载的用法总结
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • ... 是什么 ?... 有什么用处?
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .net 调用php,php 调用.net com组件 --
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .NET单元测试