什么是单例模式

对于一个类,只有一个实例化的对象,我们构建单例模式一般有两种:饿汉式和懒汉式

image-20240119092547006

饿汉式

  • 优点是无线程安全问题,类加载就创建对象
  • 缺点是占内存
1
2
3
4
5
6
7
class Singleton01{
private static Singleton01 instance = new Singleton01();//声明对象同时私有化

public static Singleton01 getInstance(){//向外声明访问该类对象的方法
return instance;
}
}

懒汉式

  • 优点是延迟加载,创建后才占用内存
  • 缺点是有线程安全问题,需要双重检查锁保证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 1.线程不安全 
class Singleton02 {
private static volatile Singleton02 instance = null;//声明对象,不实例化

public static Singleton02 getInstance(){//向外提供访问该类对象的方法
if (instance == null){
instance = new Singleton02();
}
return instance;
}
}
// 2.double-check锁保证线程安全
class Singleton02 {
// 由于锁已经保证了可见性,这里volatile的作用是防止new过程中的指令重排
private static volatile Singleton02 instance = null;//声明对象,不实例化

public static Singleton02 getInstance(){//向外提供访问该类对象的方法
if (instance == null){
synchronized(Singleton02.class){
if(instance == null){
instance = new Singleton02();
}
}
}
return instance;
}
}
// 3.CAS实现无锁线程安全创建单例
public class Singleton02 {

private static AtomicReference<Singleton02> instanceRef = new AtomicReference();

public static Singleton02 getInstance() {//向外提供访问该类对象的方法
// CAS配合自旋,CAS有volatile的语义,AtomicReference的实现是value用volatile修饰
for (; ; ) {
Singleton02 instance = instanceRef.get();
if (instance != null) return instance;
instanceRef.compareAndSet(null, new Singleton02());
}
}
}

Spring的单例模式

在Spring中,bean的scope有几种,常见的如singleton、prototype、request、session等,默认是singleton,也就是Spring的bean默认是单例的,在getBean()的时候默认先从缓存拿,如果没有才懒加载创建bean,并且创建完成之后加入缓存。

1
2
// 一级缓存,beanName -> 实例化并且初始化的成品
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

Spring的double-check

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//如果为空,则锁定全局变量并进行处理。
synchronized (this.singletonObjects) {
//如果此bean正在加载,则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//当某些方法需要提前初始化的时候则会调用addSingleFactory 方法将对应的ObjectFactory初始化策略存储在singletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//调用预先设定的getObject方法
singletonObject = singletonFactory.getObject();
//记录在缓存中,earlysingletonObjects和singletonFactories互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}