天天看點

單例模式Singleton

單例模式

     保證一個類隻有一個執行個體,并且提供一個通路他的全局通路點  --《設計模式:可複用面向對象軟體的基礎》84頁3.5節

在某些情況下我們需要一個類在任何情況下 隻需要同一個執行個體并且提供一個通路該執行個體的方法

單例模式又分懶漢和餓漢模式

懶漢模式:在你需要他的時候才會去建立對象,也就是你在調用通路該執行個體的方法的時候才會去建立

/**

* 單例模式 :懶漢模式

*

* @author 愛出走的眼睛

*/

public class Singleton {

private static Singleton singleton;

private Singleton() {

System.out.println("建立對象");

}

public static Singleton GetInstance() {

if (singleton==null) {

singleton=new Singleton();

return singleton;

//測試代碼

Singleton s1 = Singleton.GetInstance();

Singleton s2 = Singleton.GetInstance();

System.out.println(s1==s2);

//結果為 true

上述代碼并非嚴格,因為沒有考慮到多線程的環境下  下面我測試一下在多線程情況下出現的問題

public class Test {

public static void main(String[] args) {

Thread tA = new Thread() {

public void run() {

Singleton.GetInstance();

};

Thread tB = new Thread() {

tA.start();

tB.start();

列印結果為:

建立對象

因為在多線程的情況下  線程A可能在建立對象之前cpu時間片用完了進入就緒狀态,線程B配置設定到資源 這個時候由于線程A沒有執行完建立對象語句,此時線程B判斷依然對象為空,是以線程B也會去建立對象,這樣兩個線程都進入了if裡面 導緻單例模式失敗! 

嚴格的單例模式 懶漢

* 單例模式 :嚴格的懶漢模式

//使用volatile 關鍵字 禁止指令排序

private static volatile Singleton singleton;

//這裡 鎖代碼塊比鎖方法更加高效

synchronized(Singleton.class) {

if (singleton == null) {

singleton = new Singleton();

如果不懂volatile 和線程的話 需要自己補習一下同步鎖和volatile 關鍵字

餓漢模式: 不管你調用不調用 它都會去建立這個對象

餓漢代碼就簡單很多

public class SingletonHungry {

//注意這裡使用了final關鍵字

private static final SingletonHungry singleton=new SingletonHungry();

private SingletonHungry() {

public static SingletonHungry GetInstance(http://www.my516.com) {

應用場景

最簡單的一個小例子  windows系統中的任務管理器 無論你打開多少次任務管理器 他隻會有一個視窗

因為如果你打開兩個任務管理器視窗 且内容一樣 管理器需要去調用CPU去擷取這些資訊 這樣設計的目的是為了減少資源浪費 是以設計成單例模式,第二點 如果你打開兩個管理器發現内容不一樣 這樣更容易給使用者帶來誤解。

spring中的bean預設就是單例模式

線程池,資料庫連接配接池,日志對象這些也用到了單例模式

---------------------

繼續閱讀