各種創(chuàng)建單例模式的優(yōu)缺點(diǎn)
單例模式應(yīng)用于一個(gè)類只有一個(gè)實(shí)例的情況,并且為其實(shí)例提供一個(gè)全局的訪問(wèn)點(diǎn)。
特點(diǎn):
1.一個(gè)類只有一個(gè)實(shí)例
2.自己創(chuàng)建這個(gè)實(shí)例
3.整個(gè)系統(tǒng)只能用這個(gè)實(shí)例
應(yīng)用場(chǎng)景
外部資源:每臺(tái)計(jì)算機(jī)有若干個(gè)打印機(jī),但只能有一個(gè)PrinterSpooler,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)。
內(nèi)部資源:大多數(shù)軟件都有一個(gè)(或多個(gè))屬性文件存放系統(tǒng)配置,這樣的系統(tǒng)應(yīng)該有一個(gè)對(duì)象管理這些屬性文件。
實(shí)現(xiàn)方式
1.餓漢式:?jiǎn)卫龑?shí)例在類裝載時(shí)就構(gòu)建,急切初始化。(預(yù)先加載法)
/** * 餓漢式(推薦) * */ public class Singleton1 { private Singleton1() { } public static Singleton1 instance = new Singleton1(); public Singleton1 getInstance() { return instance; } }
優(yōu)點(diǎn) | 1.線程安全
2.在類加載的同時(shí)已經(jīng)創(chuàng)建好一個(gè)靜態(tài)對(duì)象,調(diào)用時(shí)反應(yīng)速度快 |
缺點(diǎn) | 資源效率不高,可能getInstance()永遠(yuǎn)不會(huì)執(zhí)行到,但執(zhí)行該類的其他靜態(tài)方法或者加載了該類(class.forName),那么這個(gè)實(shí)例仍然初始化 |
2.懶漢式:?jiǎn)卫龑?shí)例在第一次被使用時(shí)構(gòu)建,延遲初始化。
class Singleton2 { private Singleton2() { } public static Singleton2 instance = null; public static Singleton2 getInstance() { if (instance == null) {
//多個(gè)線程判斷instance都為null時(shí),在執(zhí)行new操作時(shí)多線程會(huì)出現(xiàn)重復(fù)情況 instance = new Singleton2(); } return instance; } }
懶漢式在單個(gè)線程中沒(méi)有問(wèn)題,但在多線程就可能會(huì)出現(xiàn)兩個(gè)或多個(gè)Singleton2實(shí)例情況,
雖然后面實(shí)例化的Singleton2會(huì)覆蓋前面實(shí)例化的Singleton2,但最好避免這樣的情況。
改進(jìn)方式就是加鎖synchornized
class Singleton3 { private Singleton3() { } public static Singleton3 instance = null; public static synchronized Singleton3 getInstance() { if (instance == null) { instance = new Singleton3(); } return instance; } }
優(yōu)點(diǎn) | 資源利用率高,不執(zhí)行g(shù)etInstance()就不會(huì)被實(shí)例,可以執(zhí)行該類的其他靜態(tài)方法 |
缺點(diǎn) | 第一次加載時(shí)不夠快,多線程使用不必要的同步開(kāi)銷大 |
3.雙重檢測(cè)
class Singleton4 { private Singleton4() { } public static Singleton4 instance = null; public static Singleton4 getInstance() { if (instance == null) { synchronized (Singleton4.class) { if (instance == null) { instance = new Singleton4(); } } } return instance; } }
優(yōu)點(diǎn) | 資源利用率高,不執(zhí)行g(shù)etInstance()就不被實(shí)例,可以執(zhí)行該類其他靜態(tài)方法 |
缺點(diǎn) | 第一次加載時(shí)反應(yīng)不快,由于java內(nèi)存模型一些原因偶爾失敗 |
4.靜態(tài)內(nèi)部類
class Singleton5 { private Singleton5() { } private static class SingletonHelp { static Singleton5 instance = new Singleton5(); } public static Singleton5 getInstance() { return SingletonHelp.instance; } }
優(yōu)點(diǎn) | 資源利用率高,不執(zhí)行g(shù)etInstance()不被實(shí)例,可以執(zhí)行該類其他靜態(tài)方法 |
缺點(diǎn) | 第一次加載時(shí)反應(yīng)不夠快 |
總結(jié):一般采用餓漢式(1),若對(duì)資源十分在意可以采用靜態(tài)內(nèi)部類(4),不建議采用懶漢式及雙重檢測(cè)(2、3)
另外
對(duì)于第二種可以采用volatile方式
volatile用更低的代價(jià)代替同步
解釋:同步的代價(jià)主要有覆蓋范圍決定,如果可以降低同步的覆蓋范圍,可大幅提升性能。
而volatile覆蓋范圍是變量級(jí)別的,因此同步代價(jià)很低。
volatile原理:告訴處理器,不要將其放入工作內(nèi)存,而是直接在主存操作。因此,當(dāng)多處理器或多線程在訪問(wèn)該變量時(shí)
都將直接操作主存,這在本質(zhì)上做到了變量共享。
volation優(yōu)勢(shì):
1.更大的程度吞吐量
2.更少的代碼實(shí)現(xiàn)多線程
3.程序伸縮性好
4.比較好理解,無(wú)需太高的學(xué)習(xí)成本
volatile不足:
1.容易出問(wèn)題
2.比較難設(shè)計(jì)
參考文獻(xiàn)
http://yiminghe.iteye.com/blog/404334
http://developer.51cto.com/art/201103/249322.htm
posted on 2011-09-05 21:54 日出星辰 閱讀(3380) 評(píng)論(0) 編輯 收藏