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

线程安全的单例模式(Singleton)。

在Java中,实现线程安全的单例模式(Singleton)通常涉及确保类的实例在多线程环境中只被创建一次。有多种方法可以实现这一点,包括使用synchronized关键字、双重检查锁定(Double-Checked Locking, DCL)、静态内部类(Bill Pugh Singleton Design)以及使用java.util.concurrent包中的类。

以下是几种常见的线程安全单例模式实现:

1. 饿汉式(Eager Initialization)

饿汉式在类加载时就完成了实例的创建,因此是线程安全的。

public class Singleton {
private static final Singleton INSTANCE = new Singleton();
// 私有构造函数防止实例化
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}

2. 懒汉式(Lazy Initialization),使用synchronized方法

这种方法在需要时才创建实例,但整个getInstance方法是同步的,可能会影响性能。

public class Singleton {
private static Singleton instance;
// 私有构造函数防止实例化
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

3. 双重检查锁定(Double-Checked 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;
}
}

注意:这里使用了volatile关键字来确保instance变量的可见性,并禁止指令重排序。

4. 静态内部类(Bill Pugh Singleton Design)

这种方法利用了类加载机制来保证线程安全和延迟加载。

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

5. 使用java.util.concurrent.locks.Lock

这种方法使用Java并发包中的Lock接口来提供显式的锁控制。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Singleton {
private static Singleton instance;
private static final Lock lock = new ReentrantLock();
// 私有构造函数防止实例化
private Singleton() {}
public static Singleton getInstance() {
lock.lock();
try {
if (instance == null) {
instance = new Singleton();
}
} finally {
lock.unlock();
}
return instance;
}
}

6. 使用java.util.concurrent.atomic.AtomicReference

这种方法利用了原子变量来确保线程安全的延迟初始化。

import java.util.concurrent.atomic.AtomicReference;
public class Singleton {
private static final AtomicReference<Singleton> INSTANCE_REF = new AtomicReference<>();
// 私有构造函数防止实例化
private Singleton() {}
public static Singleton getInstance() {
Singleton instance = INSTANCE_REF.get();
if (instance == null) {
synchronized (Singleton.class) {
instance = INSTANCE_REF.get();
if (instance == null) {
instance = new Singleton();
INSTANCE_REF.set(instance);
}
}
}
return instance;
}
}

然而,这种方法实际上是双重检查锁定的一个变种,但它使用了AtomicReference来封装实例变量。在实际应用中,直接使用静态内部类或双重检查锁定通常更为简洁和高效。

总结

对于大多数应用场景,静态内部类方法(Bill Pugh Singleton Design)是首选,因为它既简单又高效,同时保证了线程安全和延迟加载。双重检查锁定也是一个不错的选择,但需要小心处理volatile关键字和指令重排序的问题。


http://www.kler.cn/a/378002.html

相关文章:

  • 全面解析Flutter中的Stream用法及实际应用
  • RabbitMQ交换机类型
  • Spring Boot 内置工具类
  • DCN网络进行新冠肺炎影像分类
  • CentOS 7 安装 ntp,自动校准系统时间
  • 如果 MySQL 主库出现了问题,从库该何去何从呢?
  • 轮廓图【HTML+CSS+JavaScript】
  • Java日志脱敏(二)——fastjson Filter + 注解 + 工具类实现
  • 统信UOS开发环境支持php
  • 使用Vite构建现代化前端应用
  • 使用AIM对SAP PO核心指标的自动化巡检监控
  • SQL,力扣题目1285,找到连续区间的开始和结束数字【窗口函数】
  • VsCode前端常用快捷键
  • 冷钱包与热钱包的差异 | 加密货币存储的安全方案
  • 03.DDD六边形架构
  • apache pdfbox 设置PDF表单域,Java生成PDF模板简单案例。
  • 【ARCGIS实验】地形特征线的提取
  • Spring Boot框架下校园社团信息管理的创新实践
  • 图像识别中的高斯滤波和椒盐滤波的适用场景与不同实现
  • SpringBoot 集成 Mybatis-Plus,LambdaQueryWrapper 使用方法
  • Git 本地操作(2)
  • Razor C# 逻辑
  • -XSS-
  • Qt的程序如何打包详细教学
  • React常用前端框架合集
  • Ubuntu下安装和配置MySQL5.7教程