單例模式

核心

保證一個(gè)類只有一個(gè)對(duì)象,并且提供一個(gè)訪問(wèn)該類的全局訪問(wèn)點(diǎn)。

優(yōu)點(diǎn)

  • 減少系統(tǒng)性能開(kāi)銷,,對(duì)象的產(chǎn)生需要較多資源時(shí),如配置文件讀取,產(chǎn)生其他依賴對(duì)象,可在應(yīng)用啟動(dòng)時(shí)直接產(chǎn)生一個(gè)單例對(duì)象,然后駐留內(nèi)存。
  • 可以優(yōu)化共享資源的訪問(wèn),如可以用一個(gè)單例類負(fù)責(zé)所有數(shù)據(jù)表的映射處理。

常見(jiàn)的五種實(shí)現(xiàn)方式

餓漢式(線程安全,調(diào)用效率高,但不能延時(shí)加載)

public class SingletonDemo {
    // 類初始化時(shí),立即加載這個(gè)類,沒(méi)有延時(shí)加載,線程安全
    private static SingletonDemo instance = new SingletonDemo();
    
    private SingletonDemo() {
        
    }
    
    public static SingletonDemo getIntance() {
        return instance;
    }

}

static變量在類裝載時(shí)初始化,虛擬機(jī)保證只會(huì)裝載一次類,肯定不會(huì)發(fā)生并發(fā)訪問(wèn)問(wèn)題。

問(wèn)題:若只是想加載類,而不是調(diào)用getInstance(),甚至永遠(yuǎn)沒(méi)調(diào)用,就會(huì)造成資源的浪費(fèi)。

懶漢式(線程安全,調(diào)用效率不高,可延時(shí)加載)

public class SingletonDemo {
    // 延時(shí)加載,真正調(diào)用時(shí)才創(chuàng)建對(duì)象
    private static SingletonDemo instance;
    
    private SingletonDemo() {
        
    }
    
    public static synchronized SingletonDemo getIntance() {
        if(instance == null) {
            instance = new SingletonDemo();
        }
        return instance;
    }

}

延遲加載,真正調(diào)用時(shí)才加載。資源利用率高。

問(wèn)題:每次調(diào)用getInstance() 都要同步,并發(fā)效率低。

雙重檢測(cè)鎖實(shí)現(xiàn)(JVM內(nèi)部模型原因,有時(shí)會(huì)有問(wèn)題,不建議使用)

public class SingletonDemo {

    private static SingletonDemo instance = null;
    
    private SingletonDemo() {
        
    }
    
    public static SingletonDemo getIntance() {
        if(instance == null) {
            SingletonDemo sc;
            synchronized (SingletonDemo.class) {
                sc = instance;
                if(sc == null) {
                    synchronized (SingletonDemo.class) {
                        if(sc == null) {
                            sc = new SingletonDemo();
                        }
                    }
                    instance = sc;
                }
            }
        }
        return instance;
    }

}

將同步內(nèi)容放到if內(nèi)部,不必每次調(diào)用時(shí)都同步,只有第一次才同步,提高了執(zhí)行效率。

問(wèn)題:由于編譯器優(yōu)化原因和JVM底層內(nèi)部模型原因,有時(shí)會(huì)出現(xiàn)問(wèn)題,不建議使用

靜態(tài)內(nèi)部類式(線程安全,調(diào)用效率高,且可延時(shí)加載)

public class SingletonDemo {
    
    private SingletonDemo() {
        
    }
    
    private static class SingletonClassInstance {
        private static final SingletonDemo instance = new SingletonDemo();  
    }
    
    private static SingletonDemo getInstance() {
        return SingletonClassInstance.instance;
    }
}

  • 外部類沒(méi)有static屬性,則不會(huì)像餓漢式那樣立即加載對(duì)象。
  • 只有真正調(diào)用getInstance(),才會(huì)加載靜態(tài)內(nèi)部類。加載類時(shí)是線程 安全的。 instance是static final
    類型,保證了內(nèi)存中只有這樣一個(gè)實(shí)例存在,而且只能被賦值一次,從而保證了線程安全性.
  • 兼?zhèn)淞瞬l(fā)高效調(diào)用和延遲加載的優(yōu)勢(shì)!

枚舉單例(線程安全,調(diào)用效率高,但不能延時(shí)加載)

public enum SingletonDemo {
    
    INSTANCE; // 代表一個(gè)實(shí)例
    
    /**
     * 根據(jù)需要添加功能處理
     */
    public void  singletonOperation() {
        
    }
    
}

優(yōu)點(diǎn):

  • 實(shí)現(xiàn)簡(jiǎn)單
  • 枚舉本身就是單例模式。由JVM從根本上提供保障!避免通過(guò)反射和反序列化的漏洞!

缺點(diǎn):不能延時(shí)加載

如何選擇

  1. 對(duì)于單例對(duì)象需要占用資源少的,不需要延時(shí)加載,可選用枚舉式和餓漢式,但枚舉式優(yōu)于餓漢式
  2. 單例對(duì)象占用資源大的,需要延時(shí)加載的,可選用靜態(tài)內(nèi)部類式和懶漢式,且靜態(tài)內(nèi)部類式優(yōu)于懶漢式。

防止反射和反序列化破解單例模式

反射和反序列化可以破解上述幾種實(shí)現(xiàn)方式,除了枚舉式外。下面是反破解方法

import java.io.ObjectStreamException;

public class SingletonDemo {
    private static SingletonDemo instance;
    /**
     * 防止反射破解單例模式
     */
    private SingletonDemo() {
        if(instance != null) {
             throw new RuntimeException();
        }
        
    }
    public static synchronized SingletonDemo getInstance() {
        if(instance == null) {
            instance = new SingletonDemo();
        }
        return instance;
    }
    /**
     * 防止反序列化破解單例模式
     */
    public Object readResolve() throws ObjectStreamException{
        return instance;
    }
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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