天天看點

Java單例模式

定義

所謂單例,就是整個程式有且僅有一個執行個體。該類負責建立自己的對象,同時確定隻有一個對象被建立。在Java,一般常用在工具類的實作或建立對象需要消耗資源。

特點

1、類構造器私有

2、持有自己類型的屬性

3、對外提供擷取執行個體的靜态方法

1、單例類隻能有一個執行個體。

2、單例類必須自己建立自己的唯一執行個體。

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

單例模式的優點

我們從單例模式的定義和實作,可以知道單例模式具有以下幾個優點:

1、在記憶體中隻有一個對象,節省記憶體空間;

2.避免頻繁的建立銷毀對象,可以提高性能;

3、避免對共享資源的多重占用,簡化通路;

4.為整個系統提供一個全局通路點。

單例的實作主要是通過以下兩個步驟:

1、将該類的構造方法定義為私有方法,這樣其他處的代碼就無法通過調用該類的構造方法來執行個體化該類的對象,隻有通過該類提供的靜态方法來得到該類的唯一執行個體;

2、在該類内提供一個靜态方法,當我們調用這個方法時,如果類持有的引用不為空就傳回這個引用,如果類保持的引用為空就建立該類的執行個體并将執行個體的引用賦予該類保持的引用。

餓漢模式

線程安全,比較常用,但容易産生垃圾,因為一開始就初始化

懶漢模式

線程不安全,延遲初始化,嚴格意義上不是不是單例模式

雙重鎖模式

線程安全,延遲初始化。這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能

雙重檢查模式,進行了兩次的判斷,第一次是為了避免不要的執行個體,第二次是為了進行同步,避免多線程問題。

由于<code>singleton=new Singleton()</code>對象的建立在JVM中可能會進行重排序,在多線程通路下存在風險,使用<code>volatile</code>修飾<code>signleton</code>執行個體變量有效,解決該問題。

靜态内部類單例模式

隻有第一次調用getInstance方法時,虛拟機才加載 Inner 并初始化instance ,隻有一個線程可以獲得對象的初始化鎖,其他線程無法進行初始化,保證對象的唯一性。

目前此方式是所有單例模式中最推薦的模式,但具體還是根據項目選擇。

枚舉單例模式

預設枚舉執行個體的建立是線程安全的,并且在任何情況下都是單例。實際上

1、枚舉類隐藏了私有的構造器。

2、枚舉類的域 是相應類型的一個執行個體對象

那麼枚舉類型日常用例是這樣子的:

枚舉單例模式在《Effective Java》中推薦的單例模式之一。但枚舉執行個體在日常開發是很少使用的,就是很簡單以導緻可讀性較差。

在以上所有的單例模式中,推薦靜态内部類單例模式。主要是非常直覺,即保證線程安全又保證唯一性。

衆所周知,單例模式是建立型模式,都會建立一個執行個體。那麼一個重要的問題就是反序列化。當執行個體被寫入到檔案到反序列化成執行個體時,我們需要重寫<code>readResolve</code>方法,以讓執行個體唯一。