單例模式整理
單例模式的使用場景:
- 配置文件的讀取。如日誌文件,應用配置。該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息
- 控制資源的情況下,方便資源之間的互相通信。如線程池等。數據庫連接操作,增刪改,如果非單例,就會有很多的對象實例創建。
- 如果當唯一實例尚未創建時,有兩個線程同時調用創建方法,那麽它們同時沒有檢測到唯一實例的存在,從而同時各自創建了一個實例, 這樣就有兩個實例被構造出來,從而違反了單例模式中實例唯一的原則。 解決這個問題的辦法是為指示類是否已經實例化的變量提供一個互斥鎖(雖然這樣會降低效率)。
懶漢式:有鎖才安全,但是效率低
public class Singleton {
private static Singleton instance;
private Singleton (){}
//線程不安全,用public static synchronized Singleton getInstance()
//的方式可以保證線程安全,但是效率低
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
餓漢式:執行效率高,但是初始化就分配內存,浪費內存
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)
這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
靜態內部類
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
單例模式整理