高并發(fā)下線程安全的單例模式

1.餓漢式

實(shí)現(xiàn)代碼:

public class MySingleton {

??// 1.餓漢式

??private static MySingleton singleton = new??MySingleton();

??private MySingleton() {

??}

??public static MySingleton getInstance() {

????return singleton;

??}

}

開(kāi)啟多線程進(jìn)行測(cè)試:

public class SingletonMain extends Thread {

??@Override

??public void run() {

?????System.out.println(MySingleton.getInstance().hashCode());

??}

??public static void main(String[] args) {

????// 創(chuàng)建多線程汰扭,一起執(zhí)行看是否生成同一對(duì)象

????SingletonMain th1 = new SingletonMain();

????SingletonMain th2 = new SingletonMain();

????SingletonMain th3 = new SingletonMain();

????th1.start();

????th2.start();

????th3.start();

??}

}

結(jié)果:

477037219

477037219

477037219

結(jié)論:hashCode值一致口叙,說(shuō)明是同一對(duì)象止吐,餓漢式單例模式線程安全

2.懶漢式

實(shí)現(xiàn)代碼

public class MySingleton {

??// 2.懶漢式

??private static MySingleton instance = null;

??private MySingleton() {

??}

??public static MySingleton getInstance() throws??InterruptedException {

????if (instance == null) {

??????// 創(chuàng)建實(shí)例之前可能會(huì)有一些準(zhǔn)備性的耗時(shí)工作

??????Thread.sleep(300);

??????instance = new MySingleton();

????}

????return instance;

??}

}

開(kāi)啟多線程進(jìn)行測(cè)試算柳,

public class SingletonMain extends Thread {

??@Override

??public void run() {

????try {

???????System.out.println(MySingleton.getInstance().hashCode());

????} catch (InterruptedException e) {

??????e.printStackTrace();

????}

??}

??public static void main(String[] args) {

????// 創(chuàng)建多線程惨好,一起執(zhí)行看是否生成同一對(duì)象

????SingletonMain th1 = new SingletonMain();

????SingletonMain th2 = new SingletonMain();

????SingletonMain th3 = new SingletonMain();

????th1.start();

????th2.start();

????th3.start();

??}

}

結(jié)果

1891072390

1139700714

477037219

結(jié)論:

不同線程輸出的hashCode值不一致,對(duì)象不同竖配,懶漢式單例模式線程不安全哨鸭。

造成不安全的原因:多個(gè)線程在進(jìn)入getInstance方法時(shí),都并沒(méi)有對(duì)象創(chuàng)建出來(lái)粥谬,導(dǎo)致所有線程都符合(instance == null)的條件肛根,導(dǎo)致對(duì)象被重復(fù)創(chuàng)建,不構(gòu)成單例的前提

2-01.?懶漢式改良版-靜態(tài)同步函數(shù)實(shí)現(xiàn)

實(shí)現(xiàn)代碼漏策,增加synchronized關(guān)鍵詞派哲,靜態(tài)同步函數(shù)實(shí)現(xiàn)線程安全

public class MySingleton {

??// 2.懶漢式

??private static MySingleton instance = null;

??private MySingleton() {

??}

??public static synchronized MySingleton getInstance()??throws InterruptedException {

????if (instance == null) {

??????// 創(chuàng)建實(shí)例之前可能會(huì)有一些準(zhǔn)備性的耗時(shí)工作

??????Thread.sleep(300);

??????instance = new MySingleton();

????}

????return instance;

??}

}

結(jié)果

1891072390

1891072390

1891072390

結(jié)論:

靜態(tài)同步函數(shù)可以實(shí)現(xiàn)懶漢式單例模式的線程安全,但是將一整個(gè)方法都進(jìn)行加鎖掺喻,會(huì)導(dǎo)致此方法的運(yùn)行效率降低芭届,繼續(xù)考慮其他方式進(jìn)行改良

2-02.??懶漢式改良版-同步代碼塊實(shí)現(xiàn)

實(shí)現(xiàn)代碼:增加synchronized關(guān)鍵詞,對(duì)指定代碼塊加鎖感耙,可以大大的提高整個(gè)方法的執(zhí)行效率褂乍,下面使用同步代碼塊實(shí)現(xiàn)

public class MySingleton {

??// 2.懶漢式

??private static MySingleton instance = null;

??private MySingleton() {

??}

??public static MySingleton getInstance() throws??InterruptedException {

????if (instance == null) {

??????// 創(chuàng)建實(shí)例之前可能會(huì)有一些準(zhǔn)備性的耗時(shí)工作

??????Thread.sleep(300);

??????synchronized (MySingleton.class) {

????????instance = new MySingleton();

??????}

????}

????return instance;

??}

}

結(jié)果

1891072390

756680587

1994444141

結(jié)論:目前此種調(diào)整方式還不能達(dá)到線程安全,繼續(xù)改良

雙檢查鎖機(jī)制

實(shí)現(xiàn)代碼

public class MySingleton {

??// 2.懶漢式

??private static MySingleton instance = null;

??private MySingleton() {

??}

??public static MySingleton getInstance() throws??InterruptedException {

????if (instance == null) {

??????// 創(chuàng)建實(shí)例之前可能會(huì)有一些準(zhǔn)備性的耗時(shí)工作

??????Thread.sleep(300);

??????synchronized (MySingleton.class) {

????????if (instance == null) {

??????????instance = new MySingleton();

????????}

??????}

????}

????return instance;

??}

}

結(jié)果:

1994444141

1994444141

1994444141

結(jié)論:

雙檢查鎖機(jī)制可以實(shí)現(xiàn)懶漢式單例模式的線程安全即硼,而且這種方式的效率相對(duì)于第一種來(lái)說(shuō)是比較高的

3.靜態(tài)內(nèi)置類實(shí)現(xiàn)單例模式

實(shí)現(xiàn)代碼

public class MySingleton {

??private static class MySingletonHandler {

????private static MySingleton singleon = new??MySingleton();

??}

??public static MySingleton getInstance() {

????return MySingletonHandler.singleon;

??}

}

開(kāi)啟多線程測(cè)試

public class SingletonMain extends Thread {

??@Override

??public void run() {

?????System.out.println(MySingleton.getInstance().hashCode());

??}

??public static void main(String[] args) {

????// 創(chuàng)建多線程树叽,一起執(zhí)行看是否生成同一對(duì)象

????SingletonMain th1 = new SingletonMain();

????SingletonMain th2 = new SingletonMain();

????SingletonMain th3 = new SingletonMain();

????th1.start();

????th2.start();

????th3.start();

??}

}

結(jié)果

1740545285

1740545285

1740545285

結(jié)論:

靜態(tài)內(nèi)置類實(shí)現(xiàn)單例模式是線程安全的

4.靜態(tài)代碼塊實(shí)現(xiàn)單例模式

實(shí)現(xiàn)代碼:靜態(tài)代碼塊中的代碼在使用類的時(shí)候就已經(jīng)執(zhí)行了,所以可以應(yīng)用靜態(tài)代碼塊的這個(gè)特性的實(shí)現(xiàn)單例設(shè)計(jì)模式谦絮。

public class MySingleton {

??// 使用靜態(tài)代碼塊實(shí)現(xiàn)單例模式

??private static MySingleton singleon = null;

??private MySingleton() {}

??static {

????singleon = new MySingleton();

??}

??public static MySingleton getInstance() {

????return singleon;

??}

}

結(jié)果

1209285429

1209285429

1209285429

結(jié)論:靜態(tài)代碼塊只在類加載時(shí)執(zhí)行题诵,因而只有一個(gè)實(shí)體對(duì)象,從結(jié)果來(lái)看层皱,線程也是安全的

5.使用枚舉數(shù)據(jù)類型實(shí)現(xiàn)單例模式

實(shí)現(xiàn)代碼

public class ClassFactory {

??private enum MyEnumSingleton {

????singletonFactory;

????private MySingleton instance;

????private MyEnumSingleton() {// 枚舉類的構(gòu)造方法在類加載是被實(shí)例化

??????instance = new MySingleton();

????}

????public MySingleton getInstance() {

??????return instance;

????}

??}

??public static MySingleton getInstance() {

????return MyEnumSingleton.singletonFactory.getInstance();

??}

}

結(jié)果

1139700714

1139700714

1139700714

結(jié)論:枚舉實(shí)現(xiàn)單例模式是線程安全的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末性锭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子叫胖,更是在濱河造成了極大的恐慌草冈,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異怎棱,居然都是意外死亡哩俭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門拳恋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凡资,“玉大人,你說(shuō)我怎么就攤上這事谬运∠读蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵梆暖,是天一觀的道長(zhǎng)伞访。 經(jīng)常有香客問(wèn)我,道長(zhǎng)轰驳,這世上最難降的妖魔是什么厚掷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮级解,結(jié)果婚禮上蝗肪,老公的妹妹穿的比我還像新娘。我一直安慰自己蠕趁,他們只是感情好薛闪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著俺陋,像睡著了一般豁延。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腊状,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天诱咏,我揣著相機(jī)與錄音,去河邊找鬼缴挖。 笑死袋狞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的映屋。 我是一名探鬼主播苟鸯,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼棚点!你這毒婦竟也來(lái)了早处?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瘫析,失蹤者是張志新(化名)和其女友劉穎砌梆,沒(méi)想到半個(gè)月后默责,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咸包,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年桃序,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烂瘫。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡媒熊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忱反,到底是詐尸還是另有隱情,我是刑警寧澤滤愕,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布温算,位于F島的核電站,受9級(jí)特大地震影響间影,放射性物質(zhì)發(fā)生泄漏注竿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一魂贬、第九天 我趴在偏房一處隱蔽的房頂上張望巩割。 院中可真熱鬧,春花似錦付燥、人聲如沸宣谈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)闻丑。三九已至,卻和暖如春勋颖,著一層夾襖步出監(jiān)牢的瞬間嗦嗡,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工饭玲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侥祭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓茄厘,卻偏偏與公主長(zhǎng)得像矮冬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子次哈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354