參考《Head First 設計模式》
單件模式 定義:確保一個類只有一個實例,並提供一個全局的訪問點。
單件模式如果沒有做同步處理,在多線程環境下很容易造成出現多個實例情況。一下三種實現方式可以解決這個問題。
實現一:
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
}
此方法是好理解的一種,但是有個缺陷,在每次調用getInstance()方法都需要進行代碼同步,所以代碼執行效率會有所降低。還有單例模式在創建實例後就不需要進行同步處理了,如果在調用程序頻繁且對性能要求較高的地方儘量少使用此方法。
實現二(急切創建實例):
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
利用這種做法,JVM在加載這個類是就馬上創建此唯一的單件實例。JVM保證在任何線程訪問uniqueInstance變量之前,一定先創建此實例。在靜態初始化器中創建單件,保證了線程安全。
如果程序總是創建並使用單件實例,或者在創建和運行時方面的負擔不太繁重,可以考慮此方法。
實現三(雙重檢查加鎖):
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
首先檢查是否創建實例了,如果未創建才進行同步。這樣一來,只有第一次纔會進行同步。第一次執行時。進入同步代碼塊後在檢查一次,這樣做確保多個線程執行時,創建唯一實例。如果仍是null,才創建實例。
注意此處用到volatile 修飾符,確保變量uniqueInstance被初始化成Singleton實例時,多個線程立即可見
。