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

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

單例模式是指在項(xiàng)目運(yùn)行中,一個(gè)類不論有多少對(duì)他的調(diào)用者,他只會(huì)存在一個(gè)實(shí)例

例1,經(jīng)典單例模式:

public class SingleTon {

    private static SingleTon singleTon = null;

    private SingleTon() {
    }

    public static SingleTon getInstance() {
        if (singleTon == null) {
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

例子中類的構(gòu)造函數(shù)私有,只能調(diào)用靜態(tài)方法getInstance( ),調(diào)用的時(shí)候會(huì)判斷當(dāng)前類有沒有被實(shí)例化,沒有則創(chuàng)建,有則返回這個(gè)已經(jīng)創(chuàng)建的實(shí)例。

但是經(jīng)典單例模式也存在問題,當(dāng)多線程操作的時(shí)候,由于多線程的實(shí)際是時(shí)間片的切換,所以當(dāng)一個(gè)線程運(yùn)行到if(singleTon == null)判斷為true,準(zhǔn)備進(jìn)入下一行,進(jìn)行實(shí)例化的時(shí)候,多線程切換到另一個(gè)線程,這時(shí)候到同樣的位置,依然為true,繼續(xù)實(shí)例化,然后當(dāng)切回之前的線程依然會(huì)實(shí)例化,導(dǎo)致存在兩個(gè)實(shí)例,單例模式也就失敗了,對(duì)于這個(gè)問題進(jìn)行優(yōu)化。

例2 餓漢模式

public class SingleTon {

    private static SingleTon singleTon = new SingleTon();

    private SingleTon() {
    }

    public static SingleTon getInstance() {
        if (singleTon == null) {
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

餓漢模式就是在,調(diào)用getInstance( )方法之前就進(jìn)行實(shí)例化,不管這個(gè)類有沒有被調(diào)用JVM中都會(huì)存在該類的實(shí)例。

例3 懶漢模式

public class SingleTon {

    private static SingleTon singleTon = null;

    private SingleTon() {
    }

    public synchronized static SingleTon getInstance() {
        if (singleTon == null) {
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

懶漢模式就是在,調(diào)用getInstance( )方法時(shí)候使用synchronized進(jìn)行同步化,必須等到一個(gè)線程中的該方法執(zhí)行完成后,再會(huì)被其他線程調(diào)用

餓漢模式在自己被加載時(shí)就將自己實(shí)例化,如果從資源利用效率角度來講,比懶漢模式稍差些。但是從速度和反應(yīng)時(shí)間以及性能的角度來講,卻要比懶漢模式要稍好些

例4 雙重檢查加鎖

public class SingleTon {
    //volatile關(guān)鍵字是為了禁止編譯器對(duì) volatile關(guān)鍵字修飾的變量進(jìn)行重排序,
    //并保證volatile變量的讀操作發(fā)生在寫操作之后
    private volatile static SingleTon singleTon = null;

    private SingleTon() {
    }

    public static SingleTon getInstance() {
        if (singleTon == null) {
            synchronized (SingleTon.class) {
                if (singleTon == null) {
                    singleTon = new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

這樣的做法會(huì)對(duì)創(chuàng)建對(duì)象進(jìn)行兩次檢查,其中一次檢查加入了同步方法,而當(dāng)?shù)诙握{(diào)用的時(shí)候不會(huì)再因?yàn)橥椒椒ㄏ男阅?,該方法也很好的解決了多線程的情況下單例模式消耗資源的問題。

例5 靜態(tài)內(nèi)部類

public class SingleTon { //完成了懶漢式的延遲加載,同時(shí)static保證了線程安全。
 
    private  SingleTon(){
    }
 
    public static SingleTon getIntance(){
        return SingletonHolder.mIntance;
    }
 
    //私有的,初始化的時(shí)候,沒有調(diào)用getIntance方法則不會(huì)加載
    private static class SingletonHolder{ 
        //static,final是jvm提供的同步機(jī)制,初始化后就無法修改了
        private static final SingleTon mIntance = new SingleTon();  
    }
 
}

這種寫法是最為推崇的寫法,利用static final關(guān)鍵字的同步機(jī)制,初始化后就無法修改保證了線程安全,使用holder的方式保證了延遲加載,不適用不會(huì)被加載

參考代碼鏈接

Gitee: https://gitee.com/singlekingdom/JavaDesignPatterns.git

?著作權(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)容