單例模式
設計模式學過差不多也有一年了 可到現在只記得零星的幾個 看來是有必要復習一遍了。有些大的對象其實我們只需要一個,比如說:線程池、緩存、日志對,充當打印機、顯卡等設備的驅動程序的對象等,這類對象只能有一個實例,如果制造出多個就會產生許多問題。
單件模式確保一個類只能有一個實例,并且提供一個全局的訪問點。
public class Singleton {
private static Singleton instance = null;
private Singleton () { }
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
private static Singleton instance = null;
private Singleton () { }
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
初看起來這段代碼沒有一點問題,但如果發生多線程的情況呢?因為多線程的不確定性,就很有可能產生很多個Singleton實例了。再來改善下讓它能夠適應多線程,如下:
public class Singleton {
private static Singleton instance = null;
private Singleton () {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
private static Singleton instance = null;
private Singleton () {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
這樣做多線程的問題是消除了,但卻產生另外的問題:以后每次訪問都需要執行同步方法,產生了嚴重的性能問題。再來改善下多線程,如下:
1、使用急切創建實例,而不使用延遲加載
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton () {}
public static Singleton getInstance() {
return instance;
}
}
現在我們依賴JVM在加載這個類時馬上創建此類的單件實例,JVM保證在任何線程訪問instance靜態變量之前先創建此實例。private static Singleton instance = new Singleton();
private Singleton () {}
public static Singleton getInstance() {
return instance;
}
}
2、使用雙重檢查加鎖,在getInstance中減少使用同步
public class Singleton {
// volatile 有效的確保當instance被初始化成實例時,多線程正確的處理instance變量。
private volatile static Singleton instance = null;
private Singleton () {}
public static Singleton getInstance() {
// 如果實例不存在就進入實例塊,只有第一次才徹底執行這里的代碼。
if (instance == null) {
// 這里有效的阻止了多線程問題的產生
synchronized (Singleton.class) {
// 進入區塊后,再檢查一次,只有實例為空才創建實例。
if (instance == null) {
instance= new Singleton();
}
}
}
return instance;
}
}
// volatile 有效的確保當instance被初始化成實例時,多線程正確的處理instance變量。
private volatile static Singleton instance = null;
private Singleton () {}
public static Singleton getInstance() {
// 如果實例不存在就進入實例塊,只有第一次才徹底執行這里的代碼。
if (instance == null) {
// 這里有效的阻止了多線程問題的產生
synchronized (Singleton.class) {
// 進入區塊后,再檢查一次,只有實例為空才創建實例。
if (instance == null) {
instance= new Singleton();
}
}
}
return instance;
}
}
posted on 2009-02-27 23:47 永遠的火焰舞者 閱讀(182) 評論(0) 編輯 收藏 所屬分類: designing pattern