Java基礎學習——多線程之單例設計模式(轉)

概念:
  Java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這裏主要介紹兩種:懶漢式單例、餓漢式單例。
  單例模式有如下特色:
  一、單例類只能有一個實例。
  二、單例類必須本身建立本身的惟一實例。
  三、單例類必須給全部其餘對象提供這一實例。
  單例模式確保某個類只有一個實例,並且自行實例化並向整個系統提供這個實例。在計算機系統中,線程池、緩存、日誌對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具備資源管理器的功能。每臺計算機能夠有若干個打印機,但只能有一個Printer Spooler,以免兩個打印做業同時輸出到打印機中。每臺計算機能夠有若干通訊端口,系統應當集中管理這些通訊端口,以免一個通訊端口同時被兩個請求同時調用。總之,選擇單例模式就是爲了不不一致狀態,避免政出多頭。設計模式

1、懶漢式單例緩存

//懶漢式單例類.在第一次調用的時候實例化本身   
public class Singleton {  
    private Singleton() {}  
    private static Singleton single =null;  
    //靜態工廠方法   
    public static Singleton getInstance() {  
         if (single == null) 
         {    
             single = new Singleton();  
             return single;  
         }    
    }  
 }

Singleton經過將構造方法限定爲private避免了類在外部被實例化,在同一個虛擬機範圍內,Singleton的惟一實例只能經過getInstance()方法訪問。
(事實上,經過Java反射機制是可以實例化構造方法爲private的類的,那基本上會使全部的Java單例實現失效。此問題在此處不作討論,姑且掩耳盜鈴地認爲反射機制不存在。)安全

可是以上懶漢式單例的實現沒有考慮線程安全問題,它是線程不安全的,併發環境下極可能出現多個Singleton實例,要實現線程安全,有如下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全,若是你第一次接觸單例模式,對線程安全不是很瞭解,能夠先跳過下面這三小條,去看餓漢式單例,等看完後面再回頭考慮線程安全的問題:多線程

一、在getInstance方法上加同步併發

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

★二、雙重檢查鎖定性能

public static Singleton getInstance()
 {  
        if (singleton == null) 
        {    
            synchronized (Singleton.class)    //靜態方法中同步代碼塊的鎖是字節碼文件,即所在類的文件
             {    
               if (singleton == null)
               {    
                  singleton = new Singleton();   
               }    
            }    
        }    
        return singleton;   
    }

三、靜態內部類線程

public class Singleton {    
    private static class LazyHolder {    
       private static final Singleton INSTANCE = new Singleton();    
    }    
    private Singleton (){}    
    public static final Singleton getInstance() {    
       return LazyHolder.INSTANCE;    
    }    
}

這種比上面一、2都好一些,既實現了線程安全,又避免了同步帶來的性能影響。設計

2、餓漢式單例日誌

//餓漢式單例類.在類初始化時,已經自行實例化   
public class Singleton {  
    private Singleton() {}  
    private static final Singleton single = new Singleton();  
    //靜態工廠方法   
    public static Singleton getInstance() {  
        return single;  
    }  
}

餓漢式在類建立的同時就已經建立好一個靜態的對象供系統使用,之後再也不改變,因此天生是線程安全的。code

餓漢式和懶漢式區別

從名字上來講,餓漢和懶漢,

餓漢就是類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了,

而懶漢比較懶,只有當調用getInstance的時候,纔回去初始化這個單例。

另外從如下再區分如下這兩種方式:

線程安全:

餓漢式天生就是線程安全的,能夠直接用於多線程而不會出現問題,

懶漢式自己是非線程安全的,爲了實現線程安全有幾種寫法,分別是上面的一、二、3,這三種實如今資源加載和性能方面有些區別。

相關文章
相關標籤/搜索