天天看點

Java設計模式(一)—— 單例模式

什麼是單例模式?

通俗的講,就是在應用程式中隻需要某個類保留唯一一個執行個體對象,不希望有更多的執行個體。單例模式是java設計模式中最簡單的設計模式之一,在應用程式中經常被用到。

單例模式的應用場景有很多,比如線程池、日志對象、緩存、資料庫連接配接池、計算機系統裝置管理器等等。這些常常都設計成全局唯一的,友善集中管理,也節省系統的開銷。

實作單例模式要注意以下三點:

1、單例類隻能有一個執行個體,不能從其他對象中new出來, 即構造器用private修飾。

2、單例類必須自己建立自己的唯一執行個體,需要實作一個方法提供這個執行個體。

3、單例類必須能給其他對象提供這一執行個體。

接下來我們講講在Java中如何實作單例模式 :

餓漢式,顧名思義指的是在類加載的時候就初始化好對象,不管有沒有用到。

懶漢式和餓漢式相對,指的在程式加載時不初始化對象,什麼時候被引用什麼時候才初始化對象,即在第一次使用的時候才去初始化對象,可以避免記憶體浪費。注意在擷取執行個體的getInstance()方法前加上了synchronized關鍵字,這是為了保證線程安全,避免多線程同一時刻擷取對象時造成生成了多個執行個體。

雙重檢查鎖是在懶漢式基礎上演變過來的,當分析懶漢式代碼時,你會發現隻有在第一次調用擷取執行個體方法時才需要同步。因為僅//2處的代碼需要同步,但隻有第一次調用才執行此行,後面的其他調用沒有執行此行,但都付出了同步的代價。為了提高效率,雙重檢查鎖應運而生,為什麼要二次檢查,分析雙重檢查鎖代碼,當第一次擷取執行個體多個線程并發到達//2處, 第一個線程執行完synchronized的代碼塊後,後面的線程仍然需要對singleton 進行第二次檢查,是以需要對執行個體對象做兩次檢查。java記憶體模型允許無序寫入,//4行代碼構造器執行之前,變量singleton可能成為非null的,是以singleton需要加上volatile關鍵字。

這種方式能達到雙檢鎖方式一樣的功效,但實作更為簡單。這種和餓漢式比較,在類加載時,singleton執行個體并沒有被初始化,需要顯示調用getInstance()方法才會轉載SingleHolder類,進而初始化singleton執行個體,是以達到了延時加載的效果。此方法在實際使用中用的最多,推薦此種寫法。

這種方式巧妙的應用了枚舉的特點,構造器本身私有,寫法簡單,自動支援序列化機制,防止多次執行個體化,擷取執行個體可以通過Singleton.INSTANCE來通路。

方式

是否支援延時初始化

實作難度

線程安全

餓漢式

不支援

簡單

安全

懶漢式

支援

雙重檢查鎖

複雜

靜态内部類

一般

枚舉