Singleton pattern
限定類對象只有一個實例
核心原理是將構(gòu)造函數(shù)私有化室埋,并且通過靜態(tài)方法獲取一個唯一的實例悔耘,在這個過程中保證線程安全诫惭。
餓漢模式
實例在類加載初始化的時候就由<clinit>函數(shù)創(chuàng)建
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
缺點:餓漢模式初始化的過早驮宴,如果僅僅調(diào)用了單例類的靜態(tài)函數(shù)沛简,也會進行初始化
懶漢模式
延遲加載:在使用時才初始化杆勇,效率高贪壳,第一次加載反應(yīng)稍慢
通過 double-checked locking 雙重檢查鎖定,實現(xiàn)線程安全
public final class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
volatile的作用:保證變量可見性和禁止指令重新排序
在這里主要是避免指令重排蚜退,否則Singleton
實例分配對象后寥袭,可能直接將instance
指向?qū)?yīng)的內(nèi)存空間,而構(gòu)造函數(shù)還在初始化成員字段关霸,此時另一個線程就會直接使用尚未初始化完成的單例對象instance
传黄,可能產(chǎn)生錯誤
靜態(tài)內(nèi)部類
線程安全,延遲了實例化队寇,只有在調(diào)用getInstance時才會實例化
public final class Singleton{
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
}
靜態(tài)內(nèi)部類的加載不需要依附外部類膘掰,在使用時才加載。不過在加載靜態(tài)內(nèi)部類的過程中也會加載外部類
枚舉單例
寫法簡單佳遣,通過Singleton.INSTANCE.getInstance()
獲取單例
class Resource{
}
public enum Singleton{
INSTANCE;
private Resource instance;
Singleton() {
instance = new Resource();
}
public Resource getInstance() {
return instance;
}
}
- enum沒有public的構(gòu)造器识埋,防止外部的額外構(gòu)造,恰好和單例模式吻合
- 用枚舉實現(xiàn)單例零渐,類似于餓漢模式窒舟,沒有實現(xiàn)延遲實例化
- 枚舉的反序列化不會生產(chǎn)新的實例
容器類
將多種單例類型注入到一個統(tǒng)一管理的容器中,在使用時根據(jù)key獲取對應(yīng)類型的對象诵盼。這種方式可以管理多種類型的單例惠豺,使用統(tǒng)一的接口進行獲取操作
public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String,Object>();
private Singleton() {
}
public static void registerService(String key, Objectinstance) {
if (!objMap.containsKey(key) ) {
objMap.put(key, instance) ;
}
}
public static ObjectgetService(String key) {
return objMap.get(key) ;
}
}