一:作用
Singleton Pattern:保證一個(gè)類(lèi)僅有一個(gè)實(shí)例米母,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)勾扭。
二:應(yīng)用場(chǎng)景
- 應(yīng)用中某個(gè)實(shí)例對(duì)象需要頻繁的被訪問(wèn)。
- 應(yīng)用中每次啟動(dòng)只會(huì)存在一個(gè)實(shí)例铁瞒。如賬號(hào)系統(tǒng)妙色,數(shù)據(jù)庫(kù)系統(tǒng)。
三:UML圖
四:實(shí)現(xiàn)方式
- lazy instantiaze 懶加載
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance() {
if (instance == null) { //line 1
instance = new Singleton(); //line 2
}
return instance;
}
}
優(yōu)點(diǎn):延遲加載(需要的時(shí)候才會(huì)加載)
缺點(diǎn):多線程容易出現(xiàn)不同步的問(wèn)題慧耍。
假設(shè)這樣的場(chǎng)景:兩個(gè)線程并發(fā)調(diào)用Singleton.getInstance()身辨,假設(shè)線程一先判斷完instance是否為null,既代碼中的line1進(jìn)入到line2的位置芍碧。剛剛判斷完畢后煌珊,JVM將CPU資源切換給線程二,由于線程一還沒(méi)執(zhí)行l(wèi)ine2泌豆,所以instance仍然是空的定庵,因此線程二執(zhí)行了new Signleton()操作。片刻之后踪危,線程一被重新喚醒洗贰,它執(zhí)行的仍然是new Signleton()操作。
- 同步鎖synchronized
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
優(yōu)點(diǎn):解決了多線程并發(fā)訪問(wèn)的問(wèn)題陨倡。
缺點(diǎn):性能問(wèn)題敛滋。 只有第一次執(zhí)行此方法的時(shí)候才需要同步,一旦設(shè)置了instance變量兴革,就不需要同步這個(gè)方法绎晃。此后的每次操作都會(huì)消耗在同步上。
關(guān)于Java的同步鎖關(guān)鍵字synchronized 杂曲,可以參見(jiàn)如下的鏈接:
[http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html]
- eagerly instantiaze餓加載
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance() {
return instance;
}
}
依賴JVM在加載這個(gè)類(lèi)的時(shí)候馬上創(chuàng)建唯一的單例實(shí)例庶艾,JVM保證在任何線程訪問(wèn)單例變量之前,一定先創(chuàng)建此單例擎勘。
缺點(diǎn):
1.如果實(shí)例開(kāi)銷(xiāo)較大咱揍,而且程序中未使用,性能損耗棚饵。
2.如實(shí)例的創(chuàng)建是依賴參數(shù)或者配置文件的煤裙,在getInstance()之前必須調(diào)用某個(gè)方法設(shè)置參數(shù)給它掩完,那樣這種單例寫(xiě)法就無(wú)法使用了。
- DCL 雙重檢查加鎖
public class Singleton {
private volatile* static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class){
instance = new Singleton();
}
}
return instance;
}
}
volatile關(guān)鍵詞保證硼砰,當(dāng)instance變量被初始化成為單例的實(shí)例時(shí)且蓬,多線程可以正確的處理instance變量。另外volatile關(guān)鍵字需在java5以上版本使用题翰。
關(guān)于更多的實(shí)現(xiàn)方式和DCL的一些問(wèn)題
1http://zz563143188.iteye.com/blog/1847029
2http://www.iteye.com/topic/575052
3http://www.360doc.com/content/11/0810/12/1542811_139352888.shtml