單例模式
定義:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。類圖如下:
代碼實現如下:
public class Singleton {
// 用靜態變量來記錄唯一的實例
private static Singleton instance;
/**
* 構造方法私有化,防止被創建,只能類內部能使用構造器
*/
private Singleton() { }
/**
* 實例化對象,並返回這個對象
* @return
*/
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 其他的方法
}
併發環境下上面的代碼會出現問題的,我們進一步修改,如下:
/**
* 實例化對象,並返回這個對象
* synchronized加鎖,可能對性能有影響哦
* @return
*/
public static synchronized SingletonThread getInstance() {
if (instance == null) {
instance = new SingletonThread();
}
return instance;
}
上面例子對性能很大的影響,那我們可以進一步改善嗎?
- 如果getInstance()的性能對應用程序不是很關鍵,就什麼都別做,不要改善了
- 使用“急切”創建實例,而不用延遲實例化的做法,代碼如下:
public class Singleton3 {
// 靜態屬性,類加載時初始化的,JVM保證唯一
private static Singleton3 instance = new Singleton3();
private Singleton3() { }
public static Singleton3 getInstance() {
return instance;
}
}
- 使用“雙重檢查加鎖”,在getInstance()中減少使用同步,不適合JDK1.4之前的版本,代碼如下;
public class Singleton4 {
// 用靜態變量來記錄唯一的實例, volatile多線程環境下保用最新的值
private volatile static Singleton4 instance;
/**
* 構造方法私有化,防止被創建,只能類內部能使用構造器
*/
private Singleton4() {
}
/**
* 實例化對象,並返回這個對象
* @return
*/
public static Singleton4 getInstance() {
if (instance == null) {
synchronized (Singleton4.class) {
if (instance == null) {
instance = new Singleton4();
}
}
}
return instance;
}
// 其他的方法
}
注意:有多個類加載器時,單利可能產生多個哦,這個要注意哦。
單例模式的應用場景:
- 應用中某個實例對象需要頻繁的被訪問。
- 應用中每次啓動只會存在一個實例。如賬號系統,數據庫系統。