单例模式的几种实现方式

embedded/2024/12/22 20:20:17/

单例模式(Singleton Pattern)是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式在需要全局状态或者希望整个应用程序中某个对象只有一个实例时非常有用。

单例模式的关键特点包括:

  1. 唯一实例:单例类通过私有构造函数和静态实例变量确保只有一个实例被创建。
  2. 全局访问点:单例类提供一个公共的静态方法,允许其他对象获取到这个唯一实例的引用。
  3. 延迟初始化:单例实例可以在第一次使用时创建,也可以在类加载时立即创建。延迟初始化有助于节省资源,因为它允许系统在需要时才创建实例。
  4. 线程安全:在多线程环境中,单例模式需要确保线程安全,避免多个线程同时创建多个实例。

实现方案的话,我这里推荐三种:

1、枚举(推荐)

java">public enum Singleton {INSTANCE;public void doSomething(String str) {System.out.println(str);}
}

《Effective Java》作者推荐的⼀种单例实现⽅式,简单⾼效,⽆需加锁,线程安全,可以避免通过 反射破坏枚举单例。

2、静态内部类(推荐)

java">public class Singleton {// 私有化构造⽅法private Singleton() {}// 对外提供获取实例的公共⽅法public static Singleton getInstance() {return SingletonInner.INSTANCE;}// 定义静态内部类private static class SingletonInner{private final static Singleton INSTANCE = new Singleton();}
}

当外部类Singleton被加载的时候,并不会创建静态内部类SingletonInner的实例对象。只有当调 ⽤getInstance()⽅法时, SingletonInner才会被加载,这个时候才会创建单例对象INSTANCE 。 INSTANCE的唯⼀性、创建过程的线程安全性,都由 JVM 来保证。 这种⽅式同样简单⾼效,⽆需加锁,线程安全,并且⽀持延时加载。

3、双重校验锁

java">public class Singleton {private volatile static Singleton uniqueInstance;// 私有化构造⽅法private Singleton() {}public  static Singleton getUniqueInstance() {//先判断对象是否已经实例过,没有实例化过才进⼊加锁代码if (uniqueInstance == null) {//类对象加锁synchronized (Singleton.class) {if (uniqueInstance == null) {uniqueInstance = new Singleton();}}}return uniqueInstance;}
}

uniqueInstance采⽤volatile关键字修饰也是很有必要的,uniqueInstance = new Singleton();这段 代码其实是分为三步执⾏: 1. 为uniqueInstance分配内存空间 2. 初始化uniqueInstance 3. 将uniqueInstance指向分配的内存地址 但是由于 JVM 具有指令重排的特性,执⾏顺序有可能变成 1->3->2。指令重排在单线程环境下不会 出现问题,但是在多线程环境下会导致⼀个线程获得还没有初始化的实例。例如,线程 T1 执⾏了 1 和 3,此时 T2 调⽤getUniqueInstance () 后发现uniqueInstance不为空,因此返回uniqueInstance ,但此时uniqueInstance还未被初始化。

这种⽅式实现起来较麻烦,但同样线程安全,⽀持延时加载。


http://www.ppmy.cn/embedded/35778.html

相关文章

c#和python的flask接口的交互

一、灰度图像的传输 c#端的传输 //读入文件夹中的图像 Mat img2 new Mat(file, ImreadModes.AnyColor); //将图像的数据转换成和相机相同的buffer数据 byte[] image_buffer new byte[img2.Width * img2.Height]; int cn img2.Channels(); //通道数 if (cn 1){//将图像的数…

【GameFi】链游 | Seraph | 区块链上的动作角色扮演 NFT 装备收集和掠夺游戏

官网下载 新赛季公告:https://www.seraph.game/#/news/357 开始时间:2024年4月19日 11:00 (UTC8) discard会有人发送一些激活码,或者有一些活动,只需要填表格关注账号,参与了就会将激活码发到你的邮箱 …

C++协程项目之协程库学习与实践(协程函数学习、线程切换实践)

网上协程实现原理大概有这么几种&#xff1a;调库、汇编、原语级别&#xff08;可能会破坏原本语义&#xff09;。我们今天简单学习和实践的是一种利用linux下库函数实现的协程。 首先来看这样一段代码&#xff1a; #include <iostream> #include <ucontext.h> #…

three.js实现三维爆炸效果

主要是split函数 <template><div class"app"><div class"btns"><button click"split">{{ isSplit ? "组合" : "分解" }}</button></div><div ref"canvesRef" class&quo…

[Docker]容器的网络类型以及云计算

目录 知识梗概 1、常用命令2 2、容器的网络类型 3、云计算 4、云计算服务的几种主要模式 知识梗概 1、常用命令2 上一篇已经学了一些常用的命令&#xff0c;这里补充两个&#xff1a; 导出镜像文件&#xff1a;[rootdocker ~]# docker save -o nginx.tar nginx:laster 导…

VTK图像处理--体绘制

参考&#xff1a; https://zhuanlan.zhihu.com/p/337054440 前言 体绘制&#xff0c;有时又称作三维重建&#xff0c;它能够通过设置不透明度值来显示提数据内部不同成分的细节。 本篇讲述了一个标准的VTK体绘制渲染流程。其中最重要的两个内容分别是&#xff1a;vtkVolumeMap…

Scratch编程v3.29.1少儿编程工具

软件介绍 SCRATCH是一款由麻省理工学院&#xff08;MIT&#xff09;媒体实验室开发的图形化编程语言和集成开发环境&#xff08;IDE&#xff09;。它的目标是让编程变得有趣、直观且易学&#xff0c;尤其是针对儿童和青少年群体。通过SCRATCH&#xff0c;用户可以通过拖放代码…

工厂自动化升级改造参考(01)--设备通信协议详解及选型

以下是整合了通信协议的特点、应用场景、优缺点以及常用接口方式的描述: 以太网/IP: 来历: 以太网是一种局域网技术,由罗伯特梅特卡夫和大卫博格在1973年开发。IP是网络层协议,负责在网络中的设备间传输数据。特点:基于标准的以太网技术,使用TCP/IP协议栈,支持高速数据传…