Spring中用到的九种设计模式一:单例

Spring中用到的九种设计模式一:单例


前言

对设计模式的总结


一、饿汉式

类加载的时候就创建了实例
优点:类加载的时候创建一次实例,避免了多线程同步问题
缺点:即使单例没被用到也会创建,浪费内存

1. 饿汉式1

public class Singleton {
    
    
    private static Singleton instance = new Singleton();
    private Singleton() {
    
     }
    public static Singleton getInstance() {
    
    
        return instance; 
    }
}

2. 饿汉式2

public class Singleton {
    
    
    private static Singleton instance = null;
    static {
    
    
        instance = new Singleton();
    }
    private Singleton() {
    
     }
    public static Singleton getInstance() {
    
    
        return this.instance; 
    }
}

二、懒汉式

优点:需要时才去创建

1. 懒汉式-非线程安全

缺点:没有考虑线程安全问题,多个线程并发调用getInstance,可能会创建多个实例

public class Singleton {
    
    
    private static Singleton instance = null;
    private Singleton() {
    
     }
    public static Singleton getInstance() {
    
    
          if (instance == null) {
    
    
                instance = new Singleton();
          }
        return instance;
    }
}

2. 懒汉式-线程安全

缺点:性能问题,添加了synchronized的函数比一般方法慢得多,若多次调用getInstance,则累积的性能损耗特别大。

public class Singleton {
    
    
    private static Singleton instance = null;
    private Singleton() {
    
     }
    public static Synchronized Singleton getInstance() {
    
    
          if (instance == null) {
    
    
                instance = new Singleton();
          }
        return instance;
    }
}

3. 懒汉式-双重校验锁

大部分情况下,同步代码块都不会执行到,提高了程序的性能。

有一种情况,两个线程ThreadA,ThreadB,如果threadA执行到了第一个if条件判断,instance = null;ThreadB也执行到了if条件判断instance = null,所以A和B会依次执行同步代码块里的代码。为了避免创建两个实例,因此又在同步代码块里添加了if条件进行二重检验。

public class Singleton {
    
    
    private static Singleton instance = null;
    private Singleton() {
    
     }
    public static Singleton getInstance() {
    
    
        if (instance == null) {
    
    
            synchronized(Singleton.class) {
    
    
                if (instance == null) {
    
    
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

隐患参考

Java单例模式的5种实现方法

三、Spring 中是如何使用的

这里spring中使用的是通过双重校验锁这种方式来做的
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

	@Nullable
	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;
	}

参考文档

Java单例模式的5种实现方法
Spring中用到的九种设计模式
Spring学习之路——单例模式和多例模式

猜你喜欢

转载自blog.csdn.net/bj_ameng/article/details/115381008