java的單例模式

java單例模式
 意義:   確保某個類有且只有一個實例。避免產生多個對象消耗過多的資源,或者某種類型的對象只應該有且既有一個。
 例如創建一個對象需要消耗資源過多,如要訪問IO和數據庫資源、網絡資源,這事就要考慮使用單例
 特點:   (1)構造方法私有化,一般爲private
               (2)通過一個靜態方法返回單例對象。
               (3)確保單例類對象只有一個,尤其是在多線程的情況下。
               (4)確保單例類對象在反序列化時,不重新構建對象。
1  懶漢式單列模式
優點:單例只有在使用的時候纔會初始化化,在一定程度上節約了資源。
缺點:第一次加載時需要及時的進行初始化,反應稍微慢,最大的問題是每次調用getInstanse
 private static Singleton instance;
      private Singleton()
      {
          
      }  
        public static Singleton getInstance()
          {       
               if(instance==null)
               {
                   instance=new Singleton();
               }
               return instance;
          }
2 餓漢式單列模式
這種方式基於classloader機制避免了多線程的同步問題,不過,instance在類裝載時就實例化
 private static Singleton instance=new Singleton();
         private Singleton()
         {
            
         }
         public static Singleton getInstance()
         {
             return instance;
         }
3 雙重檢查(不推薦)
爲處理原版非延遲加載方式瓶頸問題,我們需要對 instance 進行第二次檢查,目的是避開過多的同步(因爲這裏的同步只需在第一次創建實例時才同步,一旦創建成功,以後獲取實例時就不需要同獲取鎖了),但在Java中行不通,因爲同步塊外面的if (instance == null)可能看到已存在,但不完整的實例
 private static Singleton instance;
          private Singleton()
          {
              
          }  
         public static Singleton getInstance()
             {
                 if(instance==null)
               {
                  
                 synchronized (Singleton.class)//高併發狀態下上一種很容易產生多個實例,所以我們                                                   需要尋找線程安全的方法,首先最容易就是添加synchronized關鍵字

                 {              
                   if(instance==null)
                   {
                       instance=new Singleton();
                   }
                 }
               }
                   return instance;
             }
4 內部靜態類(安全 推薦)
由於內部靜態類只會被加載一次,故該實現方式時線程安全的!
  private Singleton()
        {
            
        }  
          
        public static Singleton getInstance()  
        {  
            return Nested.instance;       
        }  
          
        static class Nested  
        {  
            private static Singleton instance = new Singleton();  
        }     
    這種方式同樣利用了classloder的機制來保證初始化instance時只有一個線程,它跟餓漢不同的是(很細微的差別)餓漢是隻要Singleton類被裝載了,那麼instance就會被實例化(沒有達到lazy loading效果),而這種方式是Singleton類被裝載了,instance不一定被初始化。因爲SingletonHolder類沒有被主動使用,只有顯示通過調用getInstance方法時,纔會顯示裝載SingletonHolder類,從而實例化instance。想象一下,如果實例化instance很消耗資源,我想讓他延遲加載,另外一方面,我不希望在Singleton類加載時就實例化,因爲我不能確保Singleton類還可能在其他的地方被主動使用從而被加載,那麼這個時候實例化instance顯然是不合適的。這個時候,這種方式相比餓漢就顯得很合理。
5 枚舉 (推薦)
  public enum Singleton
        {
            instance;
            public void operate(){}
        }  //直接調用Singleton.instance;
    這種方式是Effective Java作者Josh Bloch 提倡的方式,它不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象,可謂是很堅強的壁壘啊,不過,個人認爲由於1.5中才加入enum特性,用這種方式寫不免讓人感覺生疏,在實際工作中,我也很少看見有人這麼寫過。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章