設計模式之禪讀書筆記-單例模式你真的掌握了嗎?
date: 2017-04-10 23:21:08
單例模式的定義
單例模式是以個比較簡單的模式,其定義如下:
Ensure a class has only one instance, and provide a global point of access to it.(確保某一個類只有一個例項,而且自行例項化並向整個系統提供這個例項。)
優點:
單例模式主要是為了避免因為建立了多個例項造成資源的浪費,且多個例項由於多次呼叫容易導致結果出現錯誤,而使用單例模式能夠保證整個應用中有且只有一個例項。可以在系統設定全域性的訪問點,優化和共享資源訪問。
缺點:
單例模式一般沒有介面,擴充困難,除了修改程式碼基本沒有第二種途徑可以實現;對測試不利,單例模式沒有完成,是不能進行測試的;單例模式與單一職責原則有衝突。
理解懶漢與餓漢:
懶漢和餓漢的本質區別,就是例項化物件的時機。
“懶漢式”是在你真正用到的時候才去建這個單例物件。
“餓漢式”類載入的時候,就把單例的初始化完成了。
如何寫好單例模式?
不好的寫法:
第一種:懶漢式。多執行緒情況下,多個執行緒可以同時通過
If(singleton == null) 建立多個Singleton(),所以是執行緒不安全的。
public Class Singleton{
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance ;
}
}
第二種 懶漢,執行緒安全。在getInstance()加上synchronized,實現同步,此時執行緒安全,但是在方法加上synchronized後,在一個執行緒執行getInstance()的,其他執行緒都被阻塞了,所以效能比較低下。
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
下面我們看比較高效+執行緒安全的寫法。
第一種: 雙重檢查鎖定(double-checked locking) ,這種寫法在第一次初始化之後,其他執行緒再來getInstance的時候會省掉很多因為同步帶來的的效能消耗。
public class Singleton{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
但是,這個版本的寫法在指令重排的情況下會出錯。
可以在 private static Singleton instance 加入 volatile 改為
private static volatile Singleton instance
volatile:這個關鍵字有兩層語義。第一層語義相信大家都比較熟悉,就是可見性。可見性指的是在一個執行緒中對該變數的修改會馬上由工作記憶體(Work Memory)寫回主記憶體(Main Memory),所以會馬上反應在其它執行緒的讀取操作中。順便一提,工作記憶體和主記憶體可以近似理解為實際電腦中的快取記憶體和主存,工作記憶體是執行緒獨享的,主存是執行緒共享的。volatile的第二層語義是禁止指令重排序優化。
這樣子應該可以了吧?
然而,禁止指令重排優化這條語義在jdk1.5以後才能正確工作
關於這個寫法存在的問題,涉及到的知識比較深入了,現在暫時不做深究,感興趣的朋友可以嘗試閱讀《深入理解JVM》裡面類載入的相關內容。
此外DCL還有其他的寫法,比如從synchronized一個類改成一個static 的Object物件。
第二種:餓漢式。缺點是它不是一種懶載入模式,單例會在載入類後一開始就被初始化。
public class Singleton{
//類載入時就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
第三種:Effective Java 推薦單例用法:靜態內部類法。這種寫法仍然使用JVM本身機制保證了執行緒安全問題;由於 SingletonHolder 是私有的,除了 getInstance() 之外沒有辦法訪問它,因此它是懶漢式的;同時讀取例項的時候不會進行同步,沒有效能缺陷。
public class Singleton {
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
相關文章
- 讀秦小波《設計模式之禪》 -- 單例模式設計模式單例
- java設計模式之單例模式你真的會了嗎?(懶漢式篇)Java設計模式單例
- 大話設計模式讀書筆記3——單例模式設計模式筆記單例
- 設計模式之單例模式(《JavaScript設計模式與開發實踐》讀書筆記)設計模式單例JavaScript筆記
- 【設計模式】你的單例模式真的是生產可用的嗎?設計模式單例
- 設計模式學習筆記之單例模式設計模式筆記單例
- 【極客思考】設計模式:你確定你真的理解了單例模式嗎?設計模式單例
- 你真的會寫單例模式嗎?單例模式
- 設計模式之“物件效能模式”: Singleton 單例模式(筆記)設計模式物件單例筆記
- 設計模式讀書筆記-命令模式薦設計模式筆記
- 設計模式你真的懂了嗎?設計模式
- 【設計模式】設計模式(一)-- 大話設計模式讀書筆記設計模式筆記
- 設計模式學習筆記——單例模式設計模式筆記單例
- 設計模式讀書筆記之介面卡模式、裝飾者模式設計模式筆記
- 設計模式讀書筆記之原型模式、釋出訂閱模式設計模式筆記原型
- 設計模式之禪之代理模式設計模式
- 大話設計模式讀書筆記1——簡單工廠模式設計模式筆記
- 您的單例模式,真的單例嗎?單例模式
- 讀秦小波《設計模式之禪》 -- 工廠模式設計模式
- 3.[研磨設計模式筆記]單例模式設計模式筆記單例
- 設計模式之☞單例模式設計模式單例
- 設計模式之單例模式設計模式單例
- 設計模式之---單例模式設計模式單例
- 大話設計模式 讀書筆記設計模式筆記
- 大話設計模式讀書筆記設計模式筆記
- 設計模式之單例設計模式設計模式單例
- 大話設計模式讀書筆記6——代理模式設計模式筆記
- 大話設計模式讀書筆記2——策略模式設計模式筆記
- 玩轉設計模式——設計模式之禪設計模式
- 你真的會寫單例模式嗎——Java實現單例模式Java
- Java設計模式學習筆記(五) 單例模式Java設計模式筆記單例
- PHP 設計模式之單例模式PHP設計模式單例
- Javascript 設計模式之單例模式JavaScript設計模式單例
- Javascript設計模式之單例模式JavaScript設計模式單例
- js設計模式之單例模式JS設計模式單例
- PHP 設計模式之——單例模式PHP設計模式單例
- 01 設計模式之單例模式設計模式單例
- 設計模式(一)之單例模式設計模式單例