java設計模式singleton原理及實現
阿新 • • 發佈:2017-06-28
最新 不必要 -- 不同 適合 所有 引用 ati cnblogs
題外話:我要變強,要變強,變強,強。
1、 Singleton的應用場景以及為什麽要使用single
Singleton是一生只能有一個實例的對象。只能由singleton自身創建一個實例。外人是無法創建實例的,外人只能使用。
由於單例模式一生只有一個對象,因此可以節省內存,加快訪問速度。比較適合在公共場合使用。比如
1)對打印機的控制;如每臺計算機可以連接多個打印機,只能有一個PrinterSpooler,以避免兩個打印作業同時輸出到打印機;
2)windows的task manager是典型的單例模式。
2、 Singleton的實現原理
1、 私有的構造方法
2、 私有靜態引用指向自己實例
3、 公有靜態方法返回自身實例
3、 Singleton的實現方式--懶漢模式(非線程安全)
package ss; /** * 非線程安全的懶漢模式 * * 優點: * 避免了在惡漢模式中沒有調用卻創建實例的情況,提高了資源利用率。 * 缺點: * 非線程安全,多個線程同時訪問的時候可能會創建出多個實例,而且這多個實例不是同一個對象, * 雖然後面創建的實例會覆蓋前面創建的實例,但是還是會出現拿到的實例不一樣的情況。解決這 * 一個問題的辦法就是加同步鎖(synchronized)。 * */ public class Singleton02 { // 私有構造方法 private Singleton02(){ }// 供內部調用的實例 private static Singleton02 instance = null; // 外部訪問的靜態方法 public static Singleton02 getInstance(){ if(null == instance){ instance = new Singleton02(); } return instance; } }
4、Singleton的實現方式--懶漢模式(線程安全)
package ss; /** * 線程安全的懶漢模式(通過加synchronized) * 優點: * 避免了Singleton02中的可能創建多個實例的問題 * * 缺點 * 同步的開銷比較大, * 事實上,僅僅在第一次調用的時候需要同步判斷,其他時候只需要判斷非空返回即可。 **/ public class Singleton03 { // 私有構造方法 private Singleton03(){ } // 供內部調用的實例 private static Singleton03 instance = null; // 外部訪問的靜態方法 public static synchronized Singleton03 getInstance(){ if(null == instance){ instance = new Singleton03(); } return instance; } }
5、Singleton的顯示方式--餓漢模式(線程安全)
package ss; /** * 餓漢模式 * 優點: * 1、線程安全 * 2、在類的加載過程中已經創建好實例,加載速度快 * 缺點: * 1、資源效率不高,實例在某些情況下實例化後,可能永遠不會調用到getInstance() */ public class Singleton01 { // 私有構造方法 private Singleton01(){} // 定義內部實例,只供內部調用 public static Singleton01 instance = new Singleton01(); // 公有外部調用方法 public static Singleton01 getInstance(){ return instance; } }
6、Singleton的實現方式--雙重鎖(不可靠)
package ss; /** * 雙重鎖模式 * 起源: * 為了應對線程安全Singleton03中的情況,雙重鎖應運而生。目的是為了避免對除了第一次調用外的所有調用都實行同步的昂貴代價。 * 同步的代價在不同的jvm間是不同的。在早期、代價相當高。隨著更高級的jvm出現,同步的代價降低了,但synchronized方法或塊依然有性能損失。 * 不考慮jvm的進步,程序員們絕對不想不必要的浪費處理時間。 * 優點: * Volatile 變量具有 synchronized 的可見性特性,但是不具備原子特性。這就是說線程能夠自動發現 volatile 變量的最新值。 * 而volatile使用時有明確的規定: * 對變量的寫操作不依賴於當前值; * 該變量沒有包含在具有其他變量的不變式中; * 只有在狀態真正獨立於程序內其他內容時才能使用 volatile。 * java內存的無序寫入將會導致,雙重鎖定失敗的問題。 * * 如何解決可參照博客: * http://blog.csdn.net/chenchaofuck1/article/details/51702129 * */ public class Singleton04 { // 私有的構造函數 private Singleton04(){} // 內部訪問的實例 private static volatile Singleton04 instance = null; // 外部訪問的靜態類 public static Singleton04 getInstance(){ if(null == instance){ synchronized(Singleton04.class){ if(null == instance){ instance = new Singleton04(); } } } return instance; } /* // 下面代碼會出現這樣的情況, // 當instance為null的時候,兩個線程並發進入if語句內部。然後,一個線程進入synchronized塊來初始化instance, // 而另一個線程則被阻斷。當一個線程退出synchronized塊時,等待著的線程進入並創建另一個singleton對象 // 基於此種情況,出現了“雙重檢查鎖定” public static Singleton04 getInstance(){ if(null == instance){ synchronized(Singleton04.class){ instance = new Singleton04(); } } return instance; } */ }
java設計模式singleton原理及實現