確保物件的唯一性——單例模式 (四)

Liuwei-Sunny發表於2012-04-02

3.5 一種更好的單例實現方法

       餓漢式單例類不能實現延遲載入,不管將來用不用始終佔據記憶體;懶漢式單例類執行緒安全控制煩瑣,而且效能受影響。可見,無論是餓漢式單例還是懶漢式單例都存在這樣那樣的問題,有沒有一種方法,能夠將兩種單例的缺點都克服,而將兩者的優點合二為一呢?答案是:Yes!下面我們來學習這種更好的被稱之為Initialization Demand Holder (IoDH)的技術。

      在IoDH中,我們在單例類中增加一個靜態(static)內部類,在該內部類中建立單例物件,再將該單例物件通過getInstance()方法返回給外部使用,實現程式碼如下所示:

//Initialization on Demand Holder
class Singleton {
	private Singleton() {
	}
	
	private static class HolderClass {
            private final static Singleton instance = new Singleton();
	}
	
	public static Singleton getInstance() {
	    return HolderClass.instance;
	}
	
	public static void main(String args[]) {
	    Singleton s1, s2; 
            s1 = Singleton.getInstance();
	    s2 = Singleton.getInstance();
	    System.out.println(s1==s2);
	}
}

       編譯並執行上述程式碼,執行結果為:true,即建立的單例物件s1s2為同一物件。由於靜態單例物件沒有作為Singleton的成員變數直接例項化,因此類載入時不會例項化Singleton,第一次呼叫getInstance()時將載入內部類HolderClass,在該內部類中定義了一個static型別的變數instance,此時會首先初始化這個成員變數,由Java虛擬機器來保證其執行緒安全性,確保該成員變數只能初始化一次。由於getInstance()方法沒有任何執行緒鎖定,因此其效能不會造成任何影響。

      通過使用IoDH,我們既可以實現延遲載入,又可以保證執行緒安全,不影響系統效能,不失為一種最好的Java語言單例模式實現方式(其缺點是與程式語言本身的特性相關,很多物件導向語言不支援IoDH)。

 

練習

分別使用餓漢式單例、帶雙重檢查鎖定機制的懶漢式單例以及IoDH技術實現負載均衡器LoadBalancer

      至此,三種單例類的實現方式我們均已學習完畢,它們分別是餓漢式單例、懶漢式單例以及IoDH

【作者:劉偉  http://blog.csdn.net/lovelion

相關文章