2018-10-31 單例模式八種寫法比較

https://www.cnblogs.com/zhaoyan001/p/6365064.html

單例模式的八種寫法

1森渐、餓漢式(靜態(tài)常量)[可用]

public class Singleton {

private final static Singleton INSTANCE = new Singleton();

private Singleton(){}

public static Singleton getInstance(){
    return INSTANCE;
}
}

優(yōu)點:這種寫法比較簡單,就是在類裝載的時候就完成實例化掸鹅。避免了線程同步問題。

缺點:在類裝載的時候就完成實例化狱庇,沒有達(dá)到Lazy Loading的效果纹坐。如果從始至終從未使用過這個實例记某,則會造成內(nèi)存的浪費。

2旱捧、餓漢式(靜態(tài)代碼塊)[可用]

public class Singleton {

private static Singleton instance;

static {
    instance = new Singleton();
}

private Singleton() {}

public static Singleton getInstance() {
    return instance;
}
}

這種方式和上面的方式其實類似独郎,只不過將類實例化的過程放在了靜態(tài)代碼塊中,也是在類裝載的時候枚赡,就執(zhí)行靜態(tài)代碼塊中的代碼氓癌,初始化類的實例。優(yōu)缺點和上面是一樣的贫橙。

3贪婉、懶漢式(線程不安全)[不可用]

public class Singleton {

private static Singleton singleton;

private Singleton() {}

public static Singleton getInstance() {
    if (singleton == null) {
        singleton = new Singleton();
    }
    return singleton;
}
}

這種寫法起到了Lazy Loading的效果,但是只能在單線程下使用卢肃。如果在多線程下疲迂,一個線程進(jìn)入了if (singleton == null)判斷語句塊星压,還未來得及往下執(zhí)行,另一個線程也通過了這個判斷語句鬼譬,這時便會產(chǎn)生多個實例娜膘。所以在多線程環(huán)境下不可使用這種方式。

4优质、懶漢式(線程安全竣贪,同步方法)[不推薦用]

public class Singleton {

private static Singleton singleton;

private Singleton() {}

public static synchronized Singleton getInstance() {
    if (singleton == null) {
        singleton = new Singleton();
    }
    return singleton;
}
} 

解決上面第三種實現(xiàn)方式的線程不安全問題,做個線程同步就可以了巩螃,于是就對getInstance()方法進(jìn)行了線程同步演怎。

缺點:效率太低了,每個線程在想獲得類的實例時候避乏,執(zhí)行g(shù)etInstance()方法都要進(jìn)行同步爷耀。而其實這個方法只執(zhí)行一次實例化代碼就夠了,后面的想獲得該類實例拍皮,直接return就行了歹叮。方法進(jìn)行同步效率太低要改進(jìn)。

5铆帽、懶漢式(線程安全咆耿,同步代碼塊)[不可用]

public class Singleton {

private static Singleton singleton;

private Singleton() {}

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

由于第四種實現(xiàn)方式同步效率太低,所以摒棄同步方法爹橱,改為同步產(chǎn)生實例化的的代碼塊萨螺。但是這種同步并不能起到線程同步的作用。跟第3種實現(xiàn)方式遇到的情形一致愧驱,假如一個線程進(jìn)入了if (singleton == null)判斷語句塊慰技,還未來得及往下執(zhí)行,另一個線程也通過了這個判斷語句组砚,這時便會產(chǎn)生多個實例吻商。

6、雙重檢查[推薦用]

public class Singleton {

private static volatile Singleton singleton;

private Singleton() {}

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

Double-Check概念對于多線程開發(fā)者來說不會陌生惫确,如代碼中所示手报,我們進(jìn)行了兩次if (singleton == null)檢查蚯舱,這樣就可以保證線程安全了改化。這樣,實例化代碼只用執(zhí)行一次枉昏,后面再次訪問時陈肛,判斷if (singleton == null),直接return實例化對象兄裂。

優(yōu)點:線程安全句旱;延遲加載阳藻;效率較高。

7谈撒、靜態(tài)內(nèi)部類[推薦用]

public class Singleton {

private Singleton() {}

private static class SingletonInstance {
    private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
    return SingletonInstance.INSTANCE;
}
}

這種方式跟餓漢式方式采用的機制類似腥泥,但又有不同。兩者都是采用了類裝載的機制來保證初始化實例時只有一個線程啃匿。不同的地方在餓漢式方式是只要Singleton類被裝載就會實例化蛔外,沒有Lazy-Loading的作用,而靜態(tài)內(nèi)部類方式在Singleton類被裝載時并不會立即實例化溯乒,而是在需要實例化時夹厌,調(diào)用getInstance方法,才會裝載SingletonInstance類裆悄,從而完成Singleton的實例化矛纹。

類的靜態(tài)屬性只會在第一次加載類的時候初始化,所以在這里光稼,JVM幫助我們保證了線程的安全性或南,在類進(jìn)行初始化時,別的線程是無法進(jìn)入的艾君。

優(yōu)點:避免了線程不安全迎献,延遲加載,效率高腻贰。

8吁恍、枚舉[推薦用]

public enum Singleton {
INSTANCE;
public void whateverMethod() {

}
}

借助JDK1.5中添加的枚舉來實現(xiàn)單例模式。不僅能避免多線程同步問題播演,而且還能防止反序列化重新創(chuàng)建新的對象冀瓦。可能是因為枚舉在JDK1.5中才添加写烤,所以在實際項目開發(fā)中翼闽,很少見人這么寫過。

優(yōu)點

系統(tǒng)內(nèi)存中該類只存在一個對象洲炊,節(jié)省了系統(tǒng)資源感局,對于一些需要頻繁創(chuàng)建銷毀的對象,使用單例模式可以提高系統(tǒng)性能暂衡。

缺點

當(dāng)想實例化一個單例類的時候询微,必須要記住使用相應(yīng)的獲取對象的方法,而不是使用new狂巢,可能會給其他開發(fā)人員造成困擾撑毛,特別是看不到源碼的時候。

適用場合

  • 需要頻繁的進(jìn)行創(chuàng)建和銷毀的對象唧领;
  • 創(chuàng)建對象時耗時過多或耗費資源過多藻雌,但又經(jīng)常用到的對象雌续;
  • 工具類對象;
  • 頻繁訪問數(shù)據(jù)庫或文件的對象胯杭。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驯杜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子做个,更是在濱河造成了極大的恐慌艇肴,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叁温,死亡現(xiàn)場離奇詭異再悼,居然都是意外死亡,警方通過查閱死者的電腦和手機膝但,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門冲九,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人跟束,你說我怎么就攤上這事莺奸。” “怎么了冀宴?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵灭贷,是天一觀的道長。 經(jīng)常有香客問我略贮,道長甚疟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任逃延,我火速辦了婚禮览妖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘揽祥。我一直安慰自己讽膏,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布拄丰。 她就那樣靜靜地躺著府树,像睡著了一般。 火紅的嫁衣襯著肌膚如雪料按。 梳的紋絲不亂的頭發(fā)上奄侠,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機與錄音站绪,去河邊找鬼遭铺。 笑死,一個胖子當(dāng)著我的面吹牛恢准,可吹牛的內(nèi)容都是我干的魂挂。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼馁筐,長吁一口氣:“原來是場噩夢啊……” “哼涂召!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起敏沉,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤果正,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盟迟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秋泳,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年攒菠,在試婚紗的時候發(fā)現(xiàn)自己被綠了迫皱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡辖众,死狀恐怖卓起,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凹炸,我是刑警寧澤戏阅,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站啤它,受9級特大地震影響奕筐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜变骡,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一救欧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锣光,春花似錦笆怠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至频丘,卻和暖如春办成,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搂漠。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工迂卢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓而克,卻偏偏與公主長得像靶壮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子员萍,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容