歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java設計模式之單例模式及其應用

Java設計模式之單例模式及其應用

日期:2017/3/1 9:06:59   编辑:Linux編程

一、 單例模式概述

Java中單例模式的定義是:一個類只有一個實例,而且自行實例化並且向整個系統提供這個實例。

優點:由於單例模式在內存中只有一個實例,減少了內存開支和系統的性能開銷;單例模式可以避免對資源的多重占用。

二、單例模式的幾種形式

1. 餓漢式單例

public class Singleton {
private static final Singleton singleton= new Singleton();
private Singleton(){
}
public Singleton getSingleton(){
return singleton;
}
}

餓漢式是線程安全的,在類開始加載的時候就完成了單例的初始化。線程安全在java並發編程實戰中是這樣定義的:當多個線程訪問某個類時,不管運行時環境采用何種調度方式或者這些線程將如何交替執行,並且在主調代碼中不需要任何額外的同步或者協同,這個類都能表現出正確的行為,那麼就稱這個類是線程安全的。

2.懶漢式單例

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

懶漢式不是線程安全的,並發環境下,可能出現多個single對象。要實現線程安全,可以采用雙重鎖:

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

三、單例模式在spring中的應用

DefaultSingletonBeanRegistry類中的getSingleton方法:

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);


protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// map緩存中查看是否存在實例
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);
}

從上面的代碼中可以看出spring在獲取單例bean的時候,采用了雙重判斷加鎖的單例模式,首先嘗試從map緩存singletonObjects中獲取實例,如果獲取不到,對singletonObjects加鎖,再到map緩存earlySingletonObjects裡面獲取,如果還是為null,就創建一個bean,並放到earlySingletonObjects中去。

Copyright © Linux教程網 All Rights Reserved