Java 单例模式最完美的写法

本文探讨了单例模式的四种实现方式,包括懒汉式、饿汉式和双检锁(DCL)。在多线程环境下,简单的懒汉式和饿汉式存在线程安全问题。双检锁解决了这一问题,但需要防止指令重排序,因此引入了volatile关键字,形成最完美的volatile DCL单例模式实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式

是设计模式的中的一种。所谓单例模式,就是就是整个系统中对象仅此一个,不会有重复的对象生成。

1.  懒汉式

顾名思义,就是比较懒,当你使用的我现场去创建对象。

// 单例对象
class SingleObject{

	private static SingleObject instance;
	//构造方法私有化
	private SingleObject(){
		System.out.println("我是 SingleObject 的构造方法");
	}
	
	public static SingleObject getInstance() {
		if(instance==null) {
			instance = new SingleObject();
			return instance;
		}
		return instance;
	}
}

2. 饿汉式

顾名思义,就是时刻保持警惕,一上来就把对象给你创建好,就等着你使用。

// 单例对象
class SingleObject{

	private static SingleObject instance = new SingleObject();;
	//构造方法私有化
	private SingleObject(){
		System.out.println("我是 SingleObject 的构造方法");
	}
	
	public static SingleObject getInstance() {
		return instance;
	}
}

注意:在单线程中 懒汉式 和 饿汉式 可以解决问题,但是在多线程的环境中,这么些是有问题的!

为了看着清晰,我们现场来测试一下:

// 单例对象
class SingleObject{

	private static SingleObject instance;
	//构造方法私有化
	private SingleObject(){
		System.out.println( Thread.currentThread().getName() + " 我是 SingleObject 的构造方法");
	}
	
	public static SingleObject getInstance() {
		if(instance == null) {
			instance = new SingleObject();
			return instance;
		}
		return instance;
	}
}
// 单例模式:饿汉式多线程测试
public class SingleDemo {
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			new Thread(()->{
				SingleObject.getInstance();
			},i+"").start();
		}
	}
}

执行结果:

所以结合多线程环境下,创建了一种新的模式

3. (DCL)双检锁

// 单例对象
class SingleObject{

	private static SingleObject instance;
	//构造方法私有化
	private SingleObject(){
		System.out.println( Thread.currentThread().getName() + " 我是 SingleObject 的构造方法");
	}
	
	public static SingleObject getInstance() {
		if(instance == null) {
			synchronized (SingleObject.class) {
				if(instance == null) {
					instance = new SingleObject();
					return instance;
				}
			}
		}
		return instance;
	}
}

双检锁(DCL),又叫双重校验锁,综合了懒汉式和饿汉式两者的优缺点整合而成。但是这个机制不一定线程安全,原因是因为它有指令重排序的存在,所以,需要加上 volatile 来禁止指令重排序。如果不了解指令重排,可以看看博客:volatile 关键字

 所以说需要禁止指令重排,保证多线程下的语义一致性,如果不加,就有一定的几率出现线程不安全问题。

4. volatile 版本 DCL(最完美)

// 单例对象(双检锁+volatile)推荐使用
class SingleObject{

	// 加上 volatile 关键字,禁止指令重排
	private static volatile SingleObject instance;
	//构造方法私有化
	private SingleObject(){
		System.out.println( Thread.currentThread().getName() + " 我是 SingleObject 的构造方法");
	}
	
	public static SingleObject getInstance() {
		if(instance == null) {
			synchronized (SingleObject.class) {
				if(instance == null) {
					instance = new SingleObject();
					return instance;
				}
			}
		}
		return instance;
	}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值