目錄
1、單例(Singleton)模式:
2、最簡單的單例模式:
3、進階:
4、延遲創建 :
5、線程安全 :
6、如何創建並發訪問效率高的單例 : Double-Check Locking
7、完整的測試用例如下:
8、Initialization on demand holder
9、單例模式序列化應該注意的問題: Singleton 的序列化
10、推薦閱讀:
1、單例(Singleton)模式:
保證一個類在系統裡只能有一個對象被實例化。
如:緩存池、數據庫連接池、線程池、一些應用服務實例等。
難點:在多線程環境中,保證實例的唯一性。
2、最簡單的單例模式:
保證該類構造方法是私有的,外部無法創建該類型的對象;
提供一個全局訪問點,方便給客戶對象提供對此單例對象的使用;
public class Singleton {
/**
* 私有變量,外界無法訪問
* 可以定義 public 類型 instance變量,把屬性直接暴露給客戶對象,則沒必要實現getInstance()方法
* 但是可讀性降低,而且直接暴露實例變量的名字給客戶程序,會增加代碼的耦合度
*/
private static Singleton instance = new Singleton();
static {
//...
}
// 唯一的 private構造方法,客戶對象無法創建該對象實例
private Singleton() {
}
// 全局訪問點
public static Singleton getInstance() {
return instance;
}
}
// 客戶使用單例模式代碼
Singleton singleton = Singleton.getInstance();
如果該實例需要比較復雜的初始化過程時,把這個過程應該寫在 static{ ... }代碼快中。
注意:此實現是線程安全的,當對個線程同時去訪問該類的 getInstance( ) 方法時,不會初始化多個不同的對象,這是因為,JVM 在加載此類時,對於 static 屬性的初始化只能由一個線程執行且僅一次。
3、進階:
Statci 在加載類時就會被初始化,出於性能等方面的考慮,我們希望延遲實例化單例對象,只有在第一次使用該類的實例時才去實例化。
4、延遲創建 :
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
我們把單例的實例化過程移至 getInstance( )方法,而不是在加載類時預先創建,當訪問此方法時,首先判斷該實例是不是已經被實例化過了,如果已被初始化,則直接返回這個對象的引用;否則,創建這個實例並初始化,最後返回這個對象引用。
使用 if (instance == null) 判斷是否實例化完成了,此方法不是線程安全的。
編寫高質量代碼 改善Java程序的151個建議 PDF高清完整版 http://www.linuxidc.com/Linux/2014-06/103388.htm
Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm
Java對象初始化順序的簡單驗證 http://www.linuxidc.com/Linux/2014-02/96220.htm
Java對象值傳遞和對象傳遞的總結 http://www.linuxidc.com/Linux/2012-12/76692.htm
Java對象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm