單例模式應(yīng)用于一個類只有一個實例的情況,,并且為其實例提供一個全局的訪問點。 特點: 1.一個類只有一個實例 2.自己創(chuàng)建這個實例 3.整個系統(tǒng)只能用這個實例 應(yīng)用場景 外部資源:每臺計算機有若干個打印機,,但只能有一個PrinterSpooler,以避免兩個打印作業(yè)同時輸出到打印機,。 內(nèi)部資源:大多數(shù)軟件都有一個(或多個)屬性文件存放系統(tǒng)配置,,這樣的系統(tǒng)應(yīng)該有一個對象管理這些屬性文件。 實現(xiàn)方式 1.餓漢式:單例實例在類裝載時就構(gòu)建,,急切初始化,。(預(yù)先加載法) public class Singleton1 { private Singleton1() { } public static Singleton1 instance = new Singleton1(); public Singleton1 getInstance() { return instance; } }
2.懶漢式:單例實例在第一次被使用時構(gòu)建,,延遲初始化,。 class Singleton2 { private Singleton2() { } public static Singleton2 instance = null; public static Singleton2 getInstance() { if (instance == null) { //多個線程判斷instance都為null時,在執(zhí)行new操作時多線程會出現(xiàn)重復(fù)情況 instance = new Singleton2(); } return instance; } } 懶漢式在單個線程中沒有問題,,但在多線程就可能會出現(xiàn)兩個或多個Singleton2實例情況,, 雖然后面實例化的Singleton2會覆蓋前面實例化的Singleton2,但最好避免這樣的情況,。 改進方式就是加鎖synchornized class Singleton3 { private Singleton3() { } public static Singleton3 instance = null; public static synchronized Singleton3 getInstance() { if (instance == null) { instance = new Singleton3(); } return instance; } }
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; } }
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; } }
總結(jié):一般采用餓漢式(1),,若對資源十分在意可以采用靜態(tài)內(nèi)部類(4),,不建議采用懶漢式及雙重檢測(2、3) 另外 對于第二種可以采用volatile方式 volatile用更低的代價代替同步 解釋:同步的代價主要有覆蓋范圍決定,,如果可以降低同步的覆蓋范圍,,可大幅提升性能,。 而volatile覆蓋范圍是變量級別的,因此同步代價很低,。 volatile原理:告訴處理器,,不要將其放入工作內(nèi)存,而是直接在主存操作,。因此,,當(dāng)多處理器或多線程在訪問該變量時 都將直接操作主存,,這在本質(zhì)上做到了變量共享,。 volation優(yōu)勢: 1.更大的程度吞吐量 2.更少的代碼實現(xiàn)多線程 3.程序伸縮性好 4.比較好理解,無需太高的學(xué)習(xí)成本 volatile不足: 1.容易出問題 2.比較難設(shè)計 |
|