轉載請註明原文地址: http://www.cnblogs.com/geekda/p/9033815.html 單例模式是23種設計模式中比較常見的一種創建式模式,使用單例模式的目的就是為了節省系統資源,做到一次定義,到處使用的效果,目前使用比較廣泛的場景是spring 的bean,使用的是註冊式單 ...
轉載請註明原文地址: http://www.cnblogs.com/geekda/p/9033815.html
單例模式是23種設計模式中比較常見的一種創建式模式,使用單例模式的目的就是為了節省系統資源,做到一次定義,到處使用的效果,目前使用比較廣泛的場景是spring 的bean,使用的是註冊式單例模式,而在常見的開發中,實現單例模式還有如下幾種方式:
1,餓漢式
餓漢式單例模式比較典型的特點,就是對象初始化的時候就已經創建好了,相比於懶漢模式不足之處是相對更耗資源,好處是不存線上程安全問題,代碼如下:
2,懶漢式
懶漢式單例模式的設計原則是單例對象初始化的時候是為空的,誰第一個用就會先創建對象,後續的方法則返回第一次創建的對象,這種方式目前存線上程安全問題
代碼如下:
3,懶漢式-加鎖版本
上面懶漢模式由於存線上程安全問題,故需要加鎖來解決此問題,代碼如下:
此種方式加鎖雖然能解決線程安全問題,但是此處加鎖線上程量大的情況會帶來性能問題,下麵提供一種比較好的解決方法雙重校驗鎖方式
4,雙重校驗鎖
此方式不僅能保證線程安全,還能提供解決性能問題,一舉兩得。代碼如下:
假如有兩個線程,同時訪問此方法第一個判斷是校驗在單例對象是否已創建,創建好則直接返回,沒有創建則進入到同步塊中,同步塊中加一個判斷的
作用是判斷此處剛好沒創建實例,則繼續創建實例,此處需要說明的是其中一個線程如果已經進入同步塊中創建好對象,由於多線程環境中對象創建的位元組碼是無序的,
所以另外一個線程可能拿到的是一個未完全初始化的對象了,為瞭解決此問題,我們在定義成員變數上加一個關鍵字:volatile,可以保證對象有序性,即保證了可見性,
這樣另外一個線程拿到的就是一個完整的對象。
5,靜態內部類
這種方式是效率比較高的定義單例方法,不僅能有效解決性能問題,還能解決線程安全問題,個人比較推薦這種,代碼如下:
以上是5種比較典型的定義單例模式的方法,當然還可以通過枚舉、註冊式方式等實現單例。