设计模式——单例模式
单例模式定义:保证创建唯一实例。
实现有很多方式但是有一个共同点:构造方法私有化。
单例模式实现需要考虑的问题:
- 保证单例
- 延迟加载
- 线程安全
- 反反射、反序列化、反克隆
下面各种实现方式就是上述问题的渐进解决。懒汉式+双重验证锁是最常用的。
一、饿汉式
public class SingletonV0 { //利用一个类只会被类加载一次创建唯一实例 private static final SingletonV0 INSTANCE = new SingletonV0(); private SingletonV0(){} public static SingletonV0 getSingletonVo(){ return INSTANCE; } }
二、懒汉式
public class SingletonV1 { private static SingletonV1 INSTANCE; private SingletonV1(){} public static SingletonV1 getInstance(){ if (INSTANCE == null){ //延迟加载 INSTANCE = new SingletonV1(); } return INSTANCE; } }
三、懒汉式+双重验证锁——最常用的方式
public class SingletonV2 { /** * 注意细节:volatile修饰 */ private static volatile SingletonV2 INSTANCE; private SingletonV2(){} public static SingletonV2 getInstance(){ //双重验证锁 if (INSTANCE == null){ synchronized (SingletonV2.class){ if (INSTANCE == null){ INSTANCE = new SingletonV2(); } } } return INSTANCE; } }
四、懒汉式+双重验证锁+反反射+反序列化+反克隆
public class SingletonV3 implements Cloneable, Serializable { /** * 注意细节:volatile修饰 */ private static volatile SingletonV3 INSTANCE; private static boolean IS_FIRST_CREATE = true; private SingletonV3(){ //反反射 if (IS_FIRST_CREATE){ synchronized (SingletonV3.class){ if (IS_FIRST_CREATE){ IS_FIRST_CREATE = false; } } }else{ throw new UnsupportedOperationException("singleton object is already init()."); } } public static SingletonV3 getInstance(){ //双重验证锁 if (INSTANCE == null){ synchronized (SingletonV3.class){ if (INSTANCE == null){ INSTANCE = new SingletonV3(); } } } return INSTANCE; } /** * 反克隆 */ @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException("singleton object not support clone"); } /** * 反序列化 */ private void readObject(ObjectInputStream in) throws InvalidObjectException { throw new InvalidObjectException("can't deserialize singleton"); } private void readObjectNoData() throws InvalidObjectException { throw new InvalidObjectException("can't deserialize singleton"); } }
五、内部静态类
public class SingletonV4 { private SingletonV4(){} /** * 利用静态内部类的延迟加载 */ private static class SingletonHolder{ private static final SingletonV4 INSTANCE = new SingletonV4(); } public SingletonV4 getInstance(){ return SingletonHolder.INSTANCE; } }
六、枚举类
用枚举类创建单例是《effective Java》中推荐使用的方法。
枚举类的实质是编译器的一个语法糖,反编译后的代码:java枚举类语法糖。
public enum SingletonV5 { /** * Java的枚举类型其实是一个编译期的一个语法糖 * enum 编译后public final class * INSTANCE 编译后 public static final SingletonV5 INSTANCE; * 静态块初始化+反克隆+反序列化 */ INSTANCE; }
七、框架中的单例模式
1、Spring单例Bean
Spring中单例模式非常多,基本都是使用懒汉式+双重验证锁的方式创建单例的。
最有代表性的实现:Spring单例Bean。
/* org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean) */ 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; }