設計模式學習筆記(三)之 單例模式

2021-10-08 05:05:10 字數 1877 閱讀 4947

今天是上班的第一天,由於沒給安排活,也不知道幹啥,於是隨便翻翻csdn看到一篇關於單例模式的講解,覺得寫的很不錯,講的簡單易懂,為了加深記憶~~(打發時間)~~寫下這篇部落格。

從書上講的來說,單例模式,這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式,單例模式是指在記憶體中只會建立且僅建立一次物件的設計模式。簡單來說就是整個程式有且僅有乙個例項。

建立的單例模式有兩種型別:

懶漢式在建立物件前需要進行判斷物件是否例項化,如果已有例項化物件直接返回,沒有則new乙個後返回。

**如下:

public

static singleton

public

static singleton getinstance()

return singleton;

}}

餓漢式在類載入時就建立好例項化的物件,待程式需要時直接返回該物件。

**如下:

public

static singleton

public

static singleton getinstance()

}

到此兩種型別的單例模式都已講解完成,但是仍然存在某些問題,試想想,在多執行緒併發的情況下餓漢式單例模式還能正常使用,而懶漢式單例模式真的只有乙個例項物件嘛?

在併發的情況下,會存在還沒有例項物件而多個執行緒進入到判斷例項物件是否為null這一步,由於還沒有建立例項物件,這些執行緒都會去建立例項,這樣就出現了問題,所以我們需要對該步進行加鎖!

改進後**如下:

public

static singleton

public

static singleton getinstance()

}}return singleton;

}}

因為需要兩次判空,且對類物件加鎖,該懶漢式寫法也被稱為:double check(雙重校驗) + lock(加鎖)

上面這段**已經近似完美了,但是還存在最後乙個問題:指令重排(這塊是看完

後才知道的)

建立乙個物件,在jvm中會經過三步:

(1)為singleton分配記憶體空間

(2)初始化singleton物件

(3)將singleton指向分配好的記憶體空間

指令重排序是指:jvm在保證最終結果正確的情況下,可以不按照程式編碼的順序執行語句,盡可能提高程式的效能

在這三步中,第2、3步有可能會發生指令重排現象,建立物件的順序變為1-3-2,會導致多個執行緒獲取物件時,有可能執行緒a建立物件的過程中,執行了1、3步驟,執行緒b判斷singleton已經不為空,獲取到未初始化的singleton物件,就會報npe異常。

使用volatile關鍵字優化後的**:

public

static singleton

public

static singleton getinstance()

}}return singleton;

}}

單例模式分為懶漢式和餓漢式兩種寫法,之前課堂上講的由於沒怎麼聽過對這些都不太熟悉,寫完這篇部落格後算是基本了解單例模式了,以後在實際**中用到時也不會顯得迷茫,要去考慮多執行緒的這種情況,因為實際專案和理想上的情況總是不一樣的,需要考慮全面!

注意事項:

(1)在開發中如果對記憶體要求比較高,那麼使用懶漢式寫法,可以在特定時候才建立該物件;

(2)不必考慮記憶體情況則推薦使用餓漢式寫法,因為簡單不易出錯!且沒有任何併發安全和效能問題

(3)為了防止多執行緒環境下,因為指令重排序導致變數報npe,需要在單例物件上新增volatile關鍵字防止指令重排序

設計模式之單例模式,學習筆記

所謂的單例模式就是說乙個物件,我們只去例項化一次,在頁面中如果有乙個物件是唯一的,那麼就可以用單例模式。var fn function name fn.prototype.getname function fn.getinstrace function var a fn.getinstrace js...

設計模式學習筆記之單例模式

什麼是單例模式?顧名思義,就是只有乙個例項,也就是說乙個應用程式中只有乙個例項物件.既然乙個系統,乙個應用程式中只有乙個例項,那麼也就說明了如果操作這乙個物件,必然涉及到共享資源,涉及到資源分配問題,資源競爭等問題.那麼我們的應用場景是什麼呢?2.池化技術.比如資料庫的連線池.每個資料庫的可支援的連...

設計模式之單例學習筆記

使用場景 當使用乙個類會消耗很大的系統資源時,沒有必要去建立多個物件,這時候我們就應該使用單例模式。而為了使建立的物件有且只有乙個,類的構造方法應該是私有的,且獲取例項的方法應該是執行緒安全的。單例的幾種實現方式 1.餓漢模式 public class test public static test...