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

【设计模式-单例】

定义

单例设计模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式常用于需要控制资源的共享访问、实现全局配置、日志记录等场景。

特点

  • 唯一性:类的实例是唯一的,且只有一个。
  • 全局访问点:提供一个静态方法,允许外界获取这个唯一实例。

实现单例模式的步骤

  • 私有化构造方法:防止外部通过构造方法直接创建对象。
  • 创建私有静态实例:该实例是类的唯一实例。
  • 提供公有静态方法:通过这个方法获取唯一实例。

实现方式

饿汉式

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

懒汉式(线程不安全)

public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}//懒汉式,线程不安全public static LazySingleton getInstance() {if (instance==null) {instance=new LazySingleton();}return instance;}
}

懒汉式(线程安全)

public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}//懒汉式,线程安全,但效率低public static synchronized LazySingleton getInstanceSafe() {if (instance==null) {instance = new LazySingleton();}return instance;}
}

静态内部类

public class Singleton {  // 静态内部类private static class SingletonHolder {  private static final Singleton INSTANCE = new Singleton();  }  private Singleton (){}  public static final Singleton getInstance() {  return SingletonHolder.INSTANCE;  }  
}  

静态内部类

  • 延迟加载:静态内部类是在第一次被访问时加载,保证了延迟加载(Lazy Initialization)。这意味着如果程序运行期间从未调用 getInstance() 方法,SingletonHelper 类和 INSTANCE 实例都不会被加载和创建。
  • 线程安全性:JVM 的类加载机制天然具有线程安全性,保证了类加载和静态变量初始化的过程不会被多线程打断。因此,即使在多线程环境下,静态内部类的单例模式也无需显式同步。

双重检查锁定

public class Singleton {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;}
}

volatile

  • 可见性:在多线程编程中,每个线程都有自己的工作内存,线程从主内存中读取变量的值到自己的工作内存中,进行操作后再写回主内存。这意味着,如果一个线程更新了一个变量的值,其他线程可能无法立即看到这个变化。
    当一个变量被声明为 volatile,它确保了该变量的修改对所有线程立即可见。也就是说,当一个线程修改了 volatile 变量的值,这个新值会立即被写回主内存,而其他线程读取这个变量时,也会直接从主内存读取最新的值。

  • 防止指令重排序:指令重排序是指编译器或处理器在优化代码时,为了提高性能,可能会改变指令的执行顺序。虽然单线程下这种优化通常不会影响程序的正确性,但在多线程环境中可能导致意想不到的错误。
    当一个变量被声明为 volatile 时,它会禁止 JVM 对这个变量的读写操作进行指令重排序。即使是在多线程环境下,所有对这个变量的读写操作都会按照程序中出现的顺序执行,从而防止由于指令重排序而导致的并发问题。

枚举

public enum Singleton {  INSTANCE;  
}

种方式是Effective Java作者Josh Bloch提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊。所以这种写法,是十分推荐的且是最优的

总结

饿汉式适用于资源不敏感的单例,因为它实例化较早。
懒汉式和双重检查锁定适合需要延迟加载的场景,但要考虑线程安全问题。
静态内部类和枚举是推荐的实现方式,因为它们在保证线程安全的同时具备良好的性能和安全性。

参考
单例模式中枚举最好

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Git 分支管理
  • 【Go语言成长之路】使用 Go 和 Gin 开发 RESTful API
  • Unity Application.Quit 长时间卡顿甚至崩溃的解决方法
  • 西圣和倍思哪款充电宝好?罗马仕无线磁吸充电宝深度实测PK!
  • 计算机网络常见面试题总结
  • k8s中的资源分类及查看命令
  • APO 新发版支持Skywalking Agent接入
  • 基于FFMPEG读取摄像头图像编码为h264
  • Selenium自动化测试 常见API的使用
  • vue中的监听器(watch,watchEffect)和计算属性(computed)
  • 95.SAP MII功能详解(08)Workbench-Transaction介绍
  • MySQL:简述事务的SQL操作
  • 48.x86游戏实战-封包抓取进图call
  • 数据结构之邻接表
  • PTA - C语言国庆题集1
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 《剑指offer》分解让复杂问题更简单
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 0基础学习移动端适配
  • CentOS7简单部署NFS
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • HTTP--网络协议分层,http历史(二)
  • MaxCompute访问TableStore(OTS) 数据
  • node 版本过低
  • python_bomb----数据类型总结
  • 汉诺塔算法
  • 聊聊redis的数据结构的应用
  • 温故知新之javascript面向对象
  • 硬币翻转问题,区间操作
  • 字符串匹配基础上
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • 带你开发类似Pokemon Go的AR游戏
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • ### RabbitMQ五种工作模式:
  • #{}和${}的区别?
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (3)llvm ir转换过程
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (四)Linux Shell编程——输入输出重定向
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • .htaccess配置常用技巧
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .Net Core 微服务之Consul(三)-KV存储分布式锁
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .NET/C#⾯试题汇总系列:⾯向对象
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .Net语言中的StringBuilder:入门到精通