Java四種單例設(shè)計(jì)模式

Java中的四種單例模式

單例模式是最容易理解的設(shè)計(jì)模式之一,介紹Java中單例模式的四種寫法。

1.基本單例模式

public class Singleton{
    private static Singleton instance=new Singleton();
    private Singleton(){}
    pulic static Singleton getInstance(){
        return instance;
    }
}

特點(diǎn):餓漢式會(huì)提前進(jìn)行實(shí)例化,沒(méi)有延遲加載,不管是否使用都會(huì)有一個(gè)已經(jīng)初始化的實(shí)例在內(nèi)存中,但不會(huì)出現(xiàn)懶漢式中的多線程問(wèn)題。

2.延遲加載單例模式

public class Singleton{
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance(){
        if(instance==null)
            return instance=new Singleton();
        else
            return instance;
    }
}

特點(diǎn):實(shí)現(xiàn)了延遲加載,但在多線程情況下可能會(huì)出現(xiàn)問(wèn)題,不能保證線程安全。

3.線程安全的延遲加載單例模式

public class Singleton{
    private static Singleton instance;
    private Singleton(){}
    public static sychronized Singleton getInstance(){
        if(instance==null)
            return instance=new Singleton();
        else
            return instance;
    }
}

特點(diǎn):實(shí)現(xiàn)了線程安全,但是由于synchronized限制了整個(gè)getInstance方法,而我們只是希望在new Singleton()時(shí)進(jìn)行加鎖,因此這種寫法會(huì)導(dǎo)致效率不高。于是有人提出以下寫法:

public class Singleton{
    private static Singleton instance;
    private Singleton(){}
    public static sychronized Singleton getInstance(){
        if(instance==null)
            sychronized(Singleton.class){
                if(instance==null)
                    instance=new Singleton();
            }
        return instance;
    }
}

思路是只需同步初始化那部分代碼,這就是所謂的雙檢鎖機(jī)制,很可惜這種寫法在很多平臺(tái)和優(yōu)化編譯器中無(wú)法編譯通過(guò),原因在于,instance=new Singleton()這行代碼在不同的編譯器中的行為是無(wú)法預(yù)知的,很有可能出現(xiàn)以下初始化情況:

變量初始化通過(guò)兩個(gè)步驟實(shí)現(xiàn):1.給變量分配內(nèi)存空間;2.調(diào)用構(gòu)造函數(shù)來(lái)初始化成員變量。

假設(shè)線程A和B都在調(diào)用getInstance,線程A先進(jìn)入,在執(zhí)行完1步驟后被踢出了CPU,然后線程B進(jìn)入,B看到的instance已經(jīng)不是null了(內(nèi)存已經(jīng)分配),于是它開(kāi)始放心大膽的使用instance,但這個(gè)是錯(cuò)誤的,因?yàn)閕nstance的成員變量還都是缺省值,A還沒(méi)來(lái)得及調(diào)用構(gòu)造方法來(lái)完成instance的初始化。

4.靜態(tài)內(nèi)部類的單例模式

public class Singleton{
    private Singleton(){}
    private static class Inner{
        private static Singleton instanceHolder=new Singleton();
    }
    public static Singleton getInstacen(){
        return Inner.instanceHolder;
    }
}

由于內(nèi)部類在編譯完成后也是一個(gè)單獨(dú)的class文件,因此在不使用的情況下Inner類是不會(huì)被加載的。同時(shí),JVM保證在類加載的過(guò)程中static代碼塊在多線程或者單線程下都正確執(zhí)行,且僅執(zhí)行一次。解決了延遲加載以及線程安全的問(wèn)題。

最后編輯于
?著作權(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)容