設(shè)計模式之單例模式

單例模式

核心作用:保證一個類只有一個實例并且提供一個訪問該實例的全局訪問點

優(yōu)點:

  • 減少系統(tǒng)開銷
  • 優(yōu)化共享資源訪問

  1. 餓漢式
public class EagerSingleton{
    // 私有化構(gòu)造器
    private EagerSingleton(){

    }
    
    // 類初始化時創(chuàng)建實例(無并發(fā)問題,不可懶加載)
    private static Singleton instance = new EagerSingleton();
    
    // 公開訪問點(沒有synchronized)
    public static EagerSingleton getInstance(){
        return instance;
    }
    
/**
 * 線程安全 不可懶加載
 * 因為不可懶加載,如果對象空間占用大,長時間不用會造成空間浪費 
 */
}
  1. 懶漢式
public class LazySingleton{
    // 私有化
    private LazySingleton(){

    }
    
    // 延遲加載
    private static LazySingleton instance;
    
    // 需要synchronized, 防止一開始有多個線程同時進入if判斷
    public static synchronized LazySingleton getInstance(){
        if(instance == null){
            instance = new LazySingleton();
        }
        return instance;
    }

/**
 * 線程安全 延遲加載
 * 但是鎖方法,效率低
 */
}
  1. DCL懶漢式
public class DCLLazySingleton{
    // 私有化
    private DCLLazySingleton(){

    }
    
    // 延遲加載
    private volatile static DCLLazySingleton instance;
    
    // 縮小synchronized的范圍,只有第一次獲取需要進入鎖,提高效率
    public static DCLLazySingleton getInstance(){
        if(instance == null){
            synchronized(DCLLazySingleton.class){
                if(instance == null){
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}

/**
 * 線程安全 延遲加載
 * 只對第一次進來需要鎖,提高效率
 * 但是不是原子性操作
 * 分為以下:
 * 1. 分配內(nèi)存
 * 2. 執(zhí)行構(gòu)造方法
 * 3. 指向地址
 * 在指令重排的情況下有可能第一個進程在還沒有出去的情況下,
 * 第二個已經(jīng)判定不為空直接出去了,
 * 實例化不完整
 * 所有需要添加volatile關(guān)鍵字,可以直接讀取最新的值(內(nèi)存中的值)
 */
  1. 靜態(tài)內(nèi)部類實現(xiàn)
public class Singleton{
    private Singleton(){

    }
    
    // 靜態(tài)內(nèi)部類
    private static class InnerClass{
        private static final Singleton instance = new Sinpleton();
    }
    
    // 訪問點
    public static Singleton getInstance(){
        return InnerClass.instance;
    }
    
/**
 * 線程安全 延遲加載
 * 因為內(nèi)部沒有static變量所以初始化時不會直接加載
 * 當(dāng)調(diào)用getInstance()方法時才會加載靜態(tài)內(nèi)部類加載內(nèi)部類里面的靜態(tài)Singleton
 * 因為是static final所有保證了instance只有一個實例
 */

}
  1. 枚舉
public enum EnumSingleton{
    INSTANCE;
    
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}
/**
 * 線程安全 不可延遲加載
 * 但是可以防止反射破壞
 */

  // getInstance 源碼:
    @CallerSensitive
    @ForceInline // to ensure Reflection.getCallerClass optimization
    public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
    {
        if (!override) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, clazz, modifiers);
        }
        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        ConstructorAccessor ca = constructorAccessor;   // read volatile
        if (ca == null) {
            ca = acquireConstructorAccessor();
        }
        @SuppressWarnings("unchecked")
        T inst = (T) ca.newInstance(initargs);
        return inst;
    }

要根據(jù)不同的情況考慮不同的實現(xiàn)方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容