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