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

单例模式创建方式

单例模式是一种常用的设计模式。其主要目的是确保某一个类只有一个实例存在。以下列出了几种创建单例模式的方式和它们各自的缺点:

1. 饿汉式 (Eager Instantiation)

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

优点: 线程安全,写法简单,在类加载的时候就实例化。

缺点: 可能存在资源浪费,如果单例没有在使用,但类已经加载,则单例对象会被初始化。

2. 懒汉式 (Lazy Instantiation)

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

优点: 延迟实例化,只有在第一次调用 getInstance 时才创建实例。

缺点: 线程不安全,如果多线程环境下,可能会多次创建实例。

3. 懒汉式线程安全版本

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

优点: 解决了线程安全问题。

缺点: 每次调用 getInstance 方法时都需要进行同步,降低了效率,同步是在整个方法上,而不是只同步临界区。

4. 双重检查锁定 (Double-Check Locking) 线程安全版

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;}
}

优点: 解决了线程安全问题并且锁住的临界区更小,只有单例为 null 时才会进行同步。

缺点: 可能存在指令重排序问题,INSTANCE = new Singleton(); 可能被拆分为多条指令,必须加入 volatile 防止指令重排。

5. 静态内部类 (Static Nested Class)

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

优点: 懒加载,线程安全,扩展性强(对反射安全)。内部类只有在外部类被调用才加载,产生INSTANCE实例,又不用加锁。

缺点: 相比饿汉式来说,可能存在一些性能上的差异。

6. 枚举 (Enum)

public enum Singleton {INSTANCE;public void someMethod() {// ...}
}

优点: 使用这种方式定义的单例几乎是不可破坏的,它不仅能够防止多次实例化,而且还能够防止反射和序列化导致单例的破坏。

缺点: 不适合所有的场景,因为枚举提供了一种单一类型,不能与继承很好地结合使用。

以上是单例模式的几种实现方式及各自的优缺点。单例模式在某些情况下对于保证全局唯一的对象非常重要,但在设计和实现中也需要注意避免其可能导致的资源浪费和线程安全问题。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 计算机网络之IPv4深度解析
  • 黄山黄小徽光影乐园:思特科技打造沉浸式光影乐园解决方案,快乐指数拉满了!
  • LabVIEW滚动轴承故障诊断系统
  • 数值计算引擎:搭建远程容器开发环境
  • html 首行缩进2字符
  • python语言day7 函数式编程 面向对象编程
  • android13顶部状态栏里面调节背光,不隐藏状态栏面板
  • CDD数据库文件制作(十一)——服务配置(0x19_DTC Code)
  • 【Qt开发】QSerialPort串口配置、发送、接收回调函数 多线程接收的串口类封装
  • 【python基础】—离线环境下,在linux中安装python包(以sqlalchemy为例)
  • SpringBoot获取不到Nacos配置信息报错,Nacos鉴权
  • 基于Python的上市公司年报数字化词频统计:深入解析与实战
  • 倒计时:可添加可删除的倒计时函数
  • 从零开始手写STL库:Map
  • C++:list类(迭代器)
  • .pyc 想到的一些问题
  • Angular4 模板式表单用法以及验证
  • echarts的各种常用效果展示
  • JavaScript创建对象的四种方式
  • PAT A1120
  • Redis的resp协议
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • XForms - 更强大的Form
  • 对超线程几个不同角度的解释
  • 基于webpack 的 vue 多页架构
  • 前端相关框架总和
  • 前端知识点整理(待续)
  • 人脸识别最新开发经验demo
  • 入手阿里云新服务器的部署NODE
  • 深度学习在携程攻略社区的应用
  • 小程序测试方案初探
  • 新手搭建网站的主要流程
  • 学习Vue.js的五个小例子
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 选择阿里云数据库HBase版十大理由
  • ​secrets --- 生成管理密码的安全随机数​
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • ${ }的特别功能
  • (70min)字节暑假实习二面(已挂)
  • (C语言)球球大作战
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (二开)Flink 修改源码拓展 SQL 语法
  • (六)Flink 窗口计算
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (一)、python程序--模拟电脑鼠走迷宫
  • (一)appium-desktop定位元素原理
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • .Net 6.0 处理跨域的方式
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .Net(C#)常用转换byte转uint32、byte转float等