單例模式學習筆記
阿新 • • 發佈:2018-12-26
單例模式
模式概念:確保一個類只有一個例項,並提供一個全域性訪問點
要點:
(1)單件模式確保程式中一個類最多隻有一個例項。
(2)單件模式也提供訪問這個例項的全域性點。
(3)在Java中實現單件模式需要私有的構造器、一個靜態方法和一個靜態變數。
(4)確定在效能和資源上的限制,然後小心地選擇適當的方案來實現單件,以解決多執行緒問題(我們必須認定所有的程式都是多執行緒的)。
(5)如果不採用第5版的Java 2,雙重檢查加鎖實現會失效。
(6)小心,你如果使用多個類載入器,可能導致單件失效而產生多個例項。
(7)如果使用JVM 1.2或之前的版本,你必須簡歷單件登錄檔,以免垃圾收集器將單件回收。
/** * 簡單單例模式,延遲建立例項 * 無法解決多執行緒訪問問題 */ public class Singleton { /*利用一個靜態變數來記錄Singleton類的唯一例項*/ private static Singleton uniqueInstance; /*把構造器宣告為私有的,只有自Singleton類內才可以呼叫構造器*/ private Singleton(){}; public static Singleton getInstance() { if(uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } }
/** * 使用同步的方法,解決多執行緒災難 * 但只有第一次執行此方法時,才需要真正的同步 * 一旦設定好uniqueInstance變數,就不再需要同步方法了 * 這種方法會影響程式執行效率 */ public class Singleton { /*利用一個靜態變數來記錄Singleton類的唯一例項*/ private static Singleton uniqueInstance; /*把構造器宣告為私有的,只有自Singleton類內才可以呼叫構造器*/ private Singleton(){}; public static synchronized Singleton getInstance() { if(uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } }
/** * 使用“急切”建立例項,而不用延遲例項化的做法 * 如果程式總是建立並使用單件例項,或者在建立和執行的負擔不太繁重,可以採用此方法 */ public class Singleton { /*利用一個靜態變數來記錄Singleton類的唯一例項*/ private static Singleton uniqueInstance = new Singleton(); /*把構造器宣告為私有的,只有自Singleton類內才可以呼叫構造器*/ private Singleton(){}; public static Singleton getInstance() { return uniqueInstance; } }
/**
* 用“雙重檢查加鎖”,在getInstance()中減少使用同步
* 如果效能是你關心的重點,這種做法可以幫你大大減少getInstance()的時間耗費
* volatile關鍵詞確保,當uniqueInstance變數被初始化成Singleton例項時多個執行緒能正確處理uniqueInstance變數
* 兩次null檢查是為了防止2個執行緒同時發現instance==null,然後同時呼叫同步塊,產生二次例項化
* 兩次null檢查後,第二個進入syncInit的執行緒將發現那個物件已經不再是null了
*/
public class Singleton {
/*利用一個靜態變數來記錄Singleton類的唯一例項*/
private volatile static Singleton uniqueInstance;
/*把構造器宣告為私有的,只有自Singleton類內才可以呼叫構造器*/
private Singleton(){};
public static Singleton getInstance() {
if(uniqueInstance == null) {
synchronized (Singleton.class) {
/*進入區塊後,再檢查一次,如果仍是null,才建立例項*/
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}