設(shè)計(jì)模式學(xué)習(xí)專欄二--------單例模式

單例模式


單例模式:確保一個(gè)類最多只有一個(gè)實(shí)例筐摘,并提供一個(gè)全局訪問點(diǎn)

有些對(duì)象我們只需要一個(gè):線程池、緩存咖熟、硬件設(shè)備等
如果多個(gè)實(shí)例會(huì)有造成沖突、結(jié)果的不一致性等問題

單例模式的類圖:

image

由類圖轉(zhuǎn)化的代碼

#Singleton.java
public class Singleton {
   private static Singleton uniqeInstance=null;
   //私有的構(gòu)造方法辜昵,杜絕了在外界通過new來實(shí)例化對(duì)象
   private Singleton(){
      
   };
   //在類方法中,專門用來構(gòu)造Singleton對(duì)象堪置。并將該單例對(duì)象暴露給外界
   public static Singleton getInstance()
   {
      if(uniqeInstance==null)
      {
         uniqeInstance=new Singleton();
      }
      return uniqeInstance;
   }
}

存在的問題: 在多線程的情況下,如果多個(gè)線程同時(shí)調(diào)用getInstance()方法舀锨,則有可能會(huì)創(chuàng)建多個(gè)實(shí)例對(duì)象

多線程下可能創(chuàng)建多個(gè)實(shí)例對(duì)象的解決方案

同步(synchronized)getInstance方法

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

缺點(diǎn): 每一次調(diào)用getInstance() 都會(huì)使用鎖機(jī)制宛逗,會(huì)非常消耗資源。

“急切”創(chuàng)建實(shí)例(餓漢式)

靜態(tài)成員變量不再為null,而是一開始就為它賦值一個(gè)實(shí)例

在這種情況下雷激,類一被加載,靜態(tài)成員變量就被初始化了屎暇。 如果程序中的單例對(duì)象全都采用這種方法,但某些單例對(duì)象從來沒被使用過根悼, 那么就會(huì)造成內(nèi)存的浪費(fèi)。

public class Singleton {
   
   private static Singleton uniqeInstance=new Singleton();
   //私有的構(gòu)造方法挤巡,杜絕了在外界通過new來實(shí)例化對(duì)象
   private Singleton(){
      
   };
   //在類方法中,專門用來構(gòu)造Singleton對(duì)象
   public synchronized static Singleton getInstance()
   {
      return uniqeInstance;
   }

}

雙重檢查加鎖(延遲加載)

public volatile static ChocolateFactory uniqueInstance = null;
public static ChocolateFactory getInstance() {
   if (uniqueInstance == null) {    //第一重檢測(cè)
      synchronized (ChocolateFactory.class) {
         if (uniqueInstance == null) {      //第二重檢測(cè)
            uniqueInstance = new ChocolateFactory();
         }
      }
   }
   return uniqueInstance;
}
  1. 如果第一次實(shí)例化時(shí),有多個(gè)線程同時(shí)通過第一重檢測(cè),第二重檢測(cè)保證了只能有一個(gè)線程實(shí)例化成功.其他競(jìng)爭(zhēng)失敗的線程直接返回 已創(chuàng)建的實(shí)例
  2. 此后所有的實(shí)例化經(jīng)過第一重檢測(cè)就直接返回
  3. volatile 存在的意義 (見下, 詳細(xì)可參考并發(fā)編程與藝術(shù))
image
  • 上訴代碼是一個(gè)錯(cuò)誤的方案喉恋。在線程執(zhí)行到第4行時(shí)母廷,代碼讀到instance不為null時(shí),instance引用的對(duì)象有可能還沒有完成初始化

  • 問題的根源

    • 代碼的第七行 instance = new Instance(); 創(chuàng)建了一個(gè)對(duì)象徘意,這一行代碼可以分解為如下3行偽代碼

      • memory = allocate(); //1. 分配對(duì)象的內(nèi)存空間
      • initInstance(memory) //2. 初始化對(duì)象
      • instance = memory ; //3. 設(shè)置instance指向剛分配的內(nèi)存地址
    • 實(shí)際上,上面3行代碼的2和3有可能發(fā)生重排序玖详。 那么在多線程的情況下就有可能 訪問到未初始化的對(duì)象把介!

    • image
    • 解決方案蟋座,使用volatile修飾成員變量instance。第2/3步將會(huì)被禁止重排序向臀!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末券膀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芹彬,更是在濱河造成了極大的恐慌,老刑警劉巖舒帮,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異玩郊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)译红,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來反璃,“玉大人昵慌,你說我怎么就攤上這事≌剩” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵淳蔼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我鹉梨,道長(zhǎng),這世上最難降的妖魔是什么存皂? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任逢艘,我火速辦了婚禮骤菠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘商乎。我一直安慰自己,他們只是感情好鹉戚,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抹凳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪却桶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天颖系,我揣著相機(jī)與錄音,去河邊找鬼嘁扼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛趁啸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播不傅,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼访娶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起崖疤,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎叮趴,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眯亦,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年搔驼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舌涨。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖囊嘉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扭粱,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布蜓堕,位于F島的核電站,受9級(jí)特大地震影響套才,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜慕淡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峰髓。 院中可真熱鬧,春花似錦携兵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凛虽,卻和暖如春死遭,著一層夾襖步出監(jiān)牢的瞬間凯旋,已是汗流浹背钉迷。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工钠署, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谐鼎。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像狸棍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子草戈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345