設計模式 單例設計模式 解析

2021-08-19 20:18:11 字數 3078 閱讀 2531

1、概念:單例模式保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點

2、單例模式(singleton),定義了乙個getinstance操作,允許客戶訪問它的唯一例項。getinstance是乙個靜態方法,主要負責建立自己的唯一例項。

class singleton

public static singleton getinstance()

return instance;

}}

3、單例模式的特性:

4、單例模式的應用:

為何要用單例模式?

對於系統中的某些類來說,只有乙個例項很重要,例如,乙個系統只能有乙個視窗管理器或者檔案系統;乙個系統只能有乙個計時工具或者id(序號)生成器

比如印表機、執行緒池、對話方塊等被設定為單例模式

5、單例模式的分類:

1)懶漢式:需要用時才去建立物件

2)餓漢式:建立類的例項時就去建立物件

6、懶漢式:

//懶漢式單例類.在第一次呼叫的時候例項化自己   

public class singleton

private static singleton single=null;

//靜態工廠方法

public static singleton getinstance()

return single;

} }

將構造方法限定為private,避免了類在外部被例項化,在同乙個虛擬機器範圍內,singleton的唯一例項只能通過getinstance()方法訪問。但是以上懶漢式單例的實現沒有考慮執行緒安全的問題,它是執行緒不安全的,併發環境下可能出現多個singleton例項,要實現執行緒安全,有以下幾種方式,都是對getinstance這個方法改造,保證了懶漢式單例的執行緒安全:

(1)在getinstance方法上加同步關鍵字synchronized,但影響執行效率,乙個執行緒呼叫,其他執行緒則需等待

public static synchronized singleton getinstance()     

return single;

}

(2)加雙重檢查鎖,比較高效

public static singleton getinstance()     

}

}

return singleton;

}

需要特別注意的是一定要加volatile關鍵字,這樣才能保證在記憶體中訪問到的是最新值,從而有效的做雙重判斷,保證只有乙個instance物件

(3)靜態內部類

public class singleton 

public synchronized static singleton getinstance()

private singleton()

}

利用靜態內部類,某個執行緒在呼叫該方法時會建立乙個例項化物件

7、餓漢式:

//餓漢式單例類.在類初始化時,已經自行例項化   

public class singleton1

private static final singleton1 single = new singleton1();

//靜態工廠方法

public static singleton1 getinstance()

}

餓漢式在類建立的同時就已經建立好乙個靜態的物件供系統使用,以後不再改變,所以天生是執行緒安全的

以上三種方法的區別:

(1)在方法上加了同步,雖然執行緒安全,但是每次都要同步,會影響效能,畢竟99%的情況下是不需要同步的

(2)在getinstance中做了兩次null檢查,確保了只有第一次呼叫單例的時候才會做同步,執行緒安全,同時避免了每次都要同步的效能損耗

(3)利用classloader的機制來保證初始化是只有乙個執行緒,所以也是執行緒安全的,沒有效能損耗

8、懶漢式和餓漢式的區別:

餓漢式就是類一旦載入,就把單例初始化完成,保證getinstance的時候,單例已經是存在的了

而懶漢式比較懶,只有當呼叫getinstance的時候,才回去初始化這個單例

(1)執行緒安全:

餓漢式是執行緒安全的,可以直接用於多執行緒而不會出現問題

懶漢式本身是非執行緒安全的,為了實現執行緒安全有以上幾種方法

(2)資源載入和效能:

餓漢式在類建立的同時就例項化乙個靜態物件出來,不管之後會不會使用這個單例,都會佔據一定的記憶體,但是相應的,在第一次呼叫時速度也會更快,因為其資源已經初始化完成

懶漢式會延遲載入,在第一次使用該單例的時候才會例項化物件出來,第一次呼叫時要做初始化,如果要做的工作比較多,效能上會有些延遲,之後就和餓漢式一樣了

9、指令重排序

懶漢式的雙重檢查版本的單例模式,一定是執行緒安全的嗎?  不一定,因為在jvm的編譯過程中會存在指令重排序的問題

(1)在建立乙個物件的時候,包含三個過程:

對於singleton = new singleton(),這不是原子操作,在jvm中包含的三個過程

(2)但是,由於jvm會進行指令重排序,所以上面的第二步和第三步的順序不能保證,最終的執行順序可能是1-2-3,也可能是1-3-2,如果是1-3-2,則在3執行完畢,2未執行之前,被另乙個執行緒搶占了,這是instance已經是非null了,但是沒有初始化,所以這個執行緒會直接返回instance,然後使用,肯定報錯

(3)解決方法:把 singleton宣告成volatile,改進後的懶漢式執行緒安全(雙重檢查鎖)的**如下:

public class singleton }}

return ourinstance;

}

10、單例模式在jdk8原始碼中的使用

(1)runtime類部分原始碼如下:

/餓漢式單例設計模式

public class runtime

private runtime()

//省略很多行

}

設計模式解析之單例模式

單例模式確保某個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。單例模式是一種常見的設計模式,在計算機系統中,執行緒池 快取 日誌物件 對話方塊 印表機 資料庫操作 顯示卡的驅動程式常被設計成單例。單例模式分3種 懶漢式單例 餓漢式單例 登記式單例。單例模式有以下3個特點 1 只能有乙個例項...

設計模式 單例設計模式

歷史 最早是建築學領域的模式,然後gof四人由其引申到編碼方面,總結了23種設計模式 設計模式 解決某一類事情最行之有效的方法 2.1 體現 餓漢式,保證物件的唯一性 class singleton 私有化建構函式禁止該類建立物件 private static singleton st new si...

設計模式 單例設計模式

單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含乙個被稱為單例的特殊類。通過單例模式可以保證系統中乙個類只有乙個例項。即乙個類只有乙個物件例項 單例模式的要點有三個 一是某個類只能有乙個例項 二是它必須自行建立這個例項 三是它必須自行向整個系統提供這個例項。單例設計模式 解決的問題 可以保...