IoDH 實現的單例模式

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

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

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

  1. //Initialization on Demand Holder  
  2. class Singleton {  
  3.     private Singleton() {  
  4.     }  
  5.       
  6.     private static class HolderClass {  
  7.             private final static Singleton instance = new Singleton();  
  8.     }  
  9.       
  10.     public static Singleton getInstance() {  
  11.         return HolderClass.instance;  
  12.     }  
  13.       
  14.     public static void main(String args[]) {  
  15.         Singleton s1, s2;   
  16.             s1 = Singleton.getInstance();  
  17.         s2 = Singleton.getInstance();  
  18.         System.out.println(s1==s2);  
  19.     }  
  20. }  
//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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章