1. 程式人生 > >看到“java單例模式”腦殼疼,學會這幾招分分鐘搞定

看到“java單例模式”腦殼疼,學會這幾招分分鐘搞定

c51 blog 機制 實例化 51cto 一個 windows type 圖片

單例模式

單例模式(Singleton),也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行為。

比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息。這種方式簡化了在復雜環境下的配置管理。

技術分享圖片

單例模式的運用場景

  • 外部資源:每臺計算機有若幹個打印機,但只能有一個PrinterSpooler,以避免兩個打印作業同時輸出到打印機。
  • Windows的Task Manager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想想看,是不是呢,你能打開兩個windows task manager嗎?
  • 多線程的線程池的設計一般也是采用單例模式,這是由於線程池要方便對池中的線程進行控制。
    技術分享圖片
    實現單例模式的方法思路

一個類能返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態方法,通常使用getInstance這個名稱);

當我們調用這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就創建該類的實例並將實例的引用賦予該類保持的引用。

同時我們 還將該類的構造函數定義為私有方法,這樣其他處的代碼就無法通過調用該類的構造函數來實例化該類的對象,只有通過該類提供的靜態方法來得到該類的唯一實例。

實現單例模式的方式

01懶漢單例式

  • 天生線程不安全:這種方式是最基本的實現方式,這種實現最大的問題就是不支持多線程。因為沒有加鎖 synchronized,所以嚴格意義上它並不算單例模式。

技術分享圖片
技術分享圖片

  • 天生線程不安全:這種方式具備很好的 lazy loading,能夠在多線程中很好的工作,但是,效率很低,99% 情況下不需要同步。
    技術分享圖片

02餓漢單列式

這種方式比較常用,但容易產生垃圾對象。

?
image
???
image
??

03靜態內部類的方式

這種方式能達到雙檢鎖方式一樣的功效,但實現更簡單。對靜態域使用延遲初始化,應使用這種方式而不是雙檢鎖方式。這種方式只適用於靜態域的情況,雙檢鎖方式可在實例域需要延遲初始化時使用。
技術分享圖片

04枚舉

這種實現方式還沒有被廣泛采用,但這是實現單例模式的最佳方法。它更簡潔,自動支持序列化機制,絕對防止多次實例化。

技術分享圖片

資源加載和性能區別
餓漢式在類創建的同時就實例化一個靜態對象出來,不管之後會不會使用這個單例,都會占據一定的內存,但是相應的,在第一次調用時速度也會更快,因為其資源已經初始化完成。

而懶漢式,會延遲加載,在第一次使用該單例的時候才會實例化對象出來,第一次調用時要做初始化,如果要做的工作比較多,性能上會有些延遲,之後就和餓漢式一樣了。

靜態內部類的方式資源利用率高,但第一次加載時反應不夠快;java中餓單例模式性能優於懶單例模式,若對資源十分在意可以采用靜態內部類。

看到“java單例模式”腦殼疼,學會這幾招分分鐘搞定