什么是单例模式
对于一个类,只有一个实例化的对象,我们构建单例模式一般有两种:饿汉式和懒汉式
饿汉式
- 优点是无线程安全问题,类加载就创建对象
- 缺点是占内存
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
| class Singleton02 { private static volatile Singleton02 instance = null; public static Singleton02 getInstance(){ if (instance == null){ instance = new Singleton02(); } return instance; } }
class Singleton02 { private static volatile Singleton02 instance = null; public static Singleton02 getInstance(){ if (instance == null){ synchronized(Singleton02.class){ if(instance == null){ instance = new Singleton02(); } } } return instance; } }
public class Singleton02 {
private static AtomicReference<Singleton02> instanceRef = new AtomicReference();
public static Singleton02 getInstance() { 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
| 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) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
|