Thread-safe singleton

單例模式的概念

單例模式就是確保只有一個實例,而且自行實例化并向整個系統(tǒng)傳遞這個實例,這個類就稱作為單例類

單例模式最重要的一個特點就是構(gòu)造方法私有化。創(chuàng)建單例模式分為懶漢式和餓漢式。

第一種:懶漢式(線程不安全的)

傳統(tǒng)的懶漢式創(chuàng)建單例模式,是線程不安全的

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

所謂懶漢式單例模式就是在調(diào)用的時候才去創(chuàng)建這個實例。這種寫法的懶加載很明顯,但是缺點就是不能再多線程訪問下正常工作。

第二種:懶漢式(線程安全的)

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

線程安全的方式創(chuàng)建單例就是在對外的創(chuàng)建實例方法上加上synchronized。 這種寫法能夠在多線程中很好的工作,而且看起來它也具備很好的lazy loading,但是,遺憾的是,效率很低,99%情況下不需要同步。

第三種:餓漢式(是線程安全的)

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

這種方式基于classloder機制避免了多線程的同步問題,不過,instance在類裝載時就實例化,雖然導(dǎo)致類裝載的原因有很多種,在單例模式中大多數(shù)都是調(diào)用getInstance方法, 但是也不能確定有其他的方式(或者其他的靜態(tài)方法)導(dǎo)致類裝載,這時候初始化instance顯然沒有達到lazy loading的效果。

第四種:靜態(tài)內(nèi)部類的方式創(chuàng)建單例模式(static inner class)

public class Singleton {
    private Singleton() {
    }
    private static class SingletonHolder {// 靜態(tài)內(nèi)部類
        private static Singleton singleton = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.singleton;
    }
}

這種方式同樣利用了classloder的機制來保證初始化instance時只有一個線程,它跟第三種方式不同的是(很細(xì)微的差別):第三種方式是只要Singleton類被裝載了,那么instance就會被實例化(沒有達到lazy loading效果),而這種方式是Singleton類被裝載了,instance不一定被初始化。因為SingletonHolder類沒有被主動使用,只有顯示通過調(diào)用getInstance方法時,才會顯示裝載SingletonHolder類,從而實例化singleton。想象一下,如果實例化singleton很消耗資源,我想讓他延遲加載,另外一方面,我不希望在Singleton類加載時就實例化,因為我不能確保Singleton類還可能在其他的地方被主動使用從而被加載,那么這個時候?qū)嵗痠nstance顯然是不合適的。這個時候,這種方式相比第三種方式就顯得很合理。

第五種:雙重校驗鎖(dubble check instance)

public class Singleton {  
  
    private static Singleton singleton;  
    private Singleton() {  
    }  
    public static Singleton getInstance(){  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
                if (singleton == null) {  
                    /** 
                     * 為什么這里會使用雙重判定呢? 
                     */  
                    singleton = new Singleton();  
                }  
            }  
        }  
        return singleton;  
    }  
}  

這種事用雙重判斷來創(chuàng)建一個單例的方法,那么我們?yōu)槭裁匆褂脙蓚€if判斷這個對象當(dāng)前是不是空的呢 ?因為當(dāng)有多個線程同時要創(chuàng)建對象的時候,多個線程有可能都停止在第一個if判斷的地方,等待鎖的釋放,然后多個線程就都創(chuàng)建了對象,這樣就不是單例模式了,所以我們要用兩個if來進行這個對象是否存在的判斷。

參考:
https://blog.csdn.net/a347911/article/details/53321803

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

  • 我第一次見到他的時候就喜歡上了他 該死的一見鐘情 他沉默寡言,卻又很帥氣,開學(xué)一個月,我們學(xué)校幾乎一半妹子都喜歡上...
    付來錢兒閱讀 558評論 1 3
  • 你終于來到這里,卻已想不起最初的心意。 喜歡的作家柏邦尼寫了這樣一條微博:“心里有苦,倒不出。千言萬語,說不出口。...
    碧云女子閱讀 565評論 4 4
  • 下載簡書已有一段時間了,大多時間都是在讀熱門的文章。今晚想寫個故事,為了她。 大學(xué)一段刻骨銘心的愛情,在畢業(yè),在異...
    孤獨夜行者閱讀 396評論 2 0
  • 當(dāng)他不再愛你的時候,你的愛便是他的負(fù)擔(dān)。請不要去計算自己的付出,更不要希望有什么回報,愛著不愛自己的人,本身便是沒...
    云殤_閱讀 407評論 4 7
  • 。好
    vogtersea閱讀 296評論 0 0

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