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

1.單例模式介紹

單例模式是一種對(duì)象創(chuàng)建模式但校,它用于產(chǎn)生一個(gè)對(duì)象的具體實(shí)例夕吻,它可以確保系統(tǒng)中一個(gè)類只產(chǎn)生一個(gè)實(shí)例线衫。java中的單例模式的討論范圍是在JVM凿可。
單例模式的好處,①對(duì)于頻繁使用的對(duì)象授账,可以省略創(chuàng)建對(duì)象所花費(fèi)的時(shí)間枯跑,這對(duì)于那些重量級(jí)對(duì)象而言,是非嘲兹龋可觀的一筆系統(tǒng)開銷敛助。②由于new操作的次數(shù)減少,因而對(duì)系統(tǒng)內(nèi)存的使用頻率也會(huì)降低屋确,這將減輕GC壓力纳击,所短GC停頓時(shí)間。

2.單例的多種寫法和各自特點(diǎn)

1.餓漢模式

public class HungurySingleton { private static final HungurySingleton mInstance = new HungurySingleton(); private HungurySingleton(){ System.out.println("create"); } public static HungurySingleton getInstance(){ return mInstance; } public static void printHello(){ System.out.println("Hello"); } public static void main(String[] args) { HungurySingleton.printHello(); } }
上面的代碼就是餓漢模式的單例攻臀,這種寫法的特點(diǎn)就是焕数,當(dāng)HungurySingleton這個(gè)類被JVM加載時(shí),單例對(duì)象就會(huì)被創(chuàng)建刨啸,正因?yàn)檫@樣堡赔,這種寫法就有一個(gè)先天不足,無法對(duì)instance實(shí)例做延時(shí)加載设联,當(dāng)執(zhí)行上面代碼時(shí)會(huì)發(fā)現(xiàn)善已,明明只是調(diào)用了HungurySingleton 的一個(gè)類方法,但是HungurySingleton實(shí)例還是被創(chuàng)建了离例。

2.懶漢模式

public class LazySingleton { private static LazySingleton mInstance; private LazySingleton(){} public static LazySingleton getInstance(){ if (mInstance == null) mInstance = new LazySingleton(); return mInstance; } }
上面代碼就是單例的懶漢模式换团,它有致命缺陷,當(dāng)在多線程環(huán)境下粘招,它根本無法保證單例啥寇,所以我們又有了線程安全的懶漢模式。
public class LazySingleton { private static LazySingleton mInstance; private LazySingleton(){} public static synchronized LazySingleton getInstance(){ if (mInstance == null) mInstance = new LazySingleton(); return mInstance; } public static LazySingleton getInstance2(){ synchronized (LazySingleton.class){ if (mInstance == null) mInstance = new LazySingleton(); return mInstance; } } }
主要是使用了synchronized關(guān)鍵字洒扎,可以用它來修飾方法辑甜,也可以使用代碼塊,但是它同樣有缺陷袍冷,就是性能效率低磷醋。

3.DCL(雙檢查鎖機(jī)制)

public class DclSingleton { private static volatile DclSingleton mInstance; private DclSingleton(){} public static DclSingleton getInstance(){ if (mInstance == null){ synchronized (DclSingleton.class){ if (mInstance == null) mInstance = new DclSingleton(); } } return mInstance; } }
DCL單例模式是對(duì)懶漢模式的一種優(yōu)化,代碼中實(shí)例被volatile所修飾胡诗,這是因?yàn)槿绻皇褂胿olatile關(guān)鍵字邓线,JVM的即時(shí)編譯器中指令重排序優(yōu)化可能會(huì)影響代碼執(zhí)行淌友,從而使代碼出錯(cuò),達(dá)不到單例效果骇陈,volatile正是解決方法震庭。關(guān)于volatile的使用以后再討論。

4.靜態(tài)內(nèi)部類寫法

public class StaticInnerSingleton { private StaticInnerSingleton(){} public static StaticInnerSingleton getInstance(){ return SingletonHolder.mInstance; } private static class SingletonHolder{ private static final StaticInnerSingleton mInstance = new StaticInnerSingleton(); } }
靜態(tài)內(nèi)部類寫法是對(duì)DCL寫法的更近一步優(yōu)化你雌,建議實(shí)際項(xiàng)目中使用器联,它寫法簡(jiǎn)單明了,線程安全婿崭,效率高拨拓,同時(shí)還能滿足延遲加載。這種寫法主要使用了JVM的同步控制氓栈,什么是同步控制渣磷,就是兩個(gè)關(guān)鍵字的使用,一個(gè)是static授瘦,一個(gè)是final醋界。static保證唯一性,final保證不可改變性奥务,這樣就能保證在JVM中這個(gè)實(shí)例時(shí)唯一且不可改變的物独,同時(shí)還是線程安全的袜硫,沒有使用synchronized關(guān)鍵字氯葬,效率還高。

5.枚舉寫法

public enum EnumSingleton { INSTANCE; public void doSomething(){} }
這就是枚舉單例的寫法婉陷,真是極簡(jiǎn)了帚称,由于枚舉是java1.5以后才有的,所以這種寫法要在1.5以后的版本中才能使用秽澳。
簡(jiǎn)簡(jiǎn)單單的一點(diǎn)代碼就實(shí)現(xiàn)了一個(gè)線程安全闯睹,lazy loading的單例,與其說是寫法鬼斧神工担神,不如說是恰如其分地應(yīng)用了enum的三個(gè)特性楼吃,自由序列化,線程安全妄讯,保證單例孩锡。

6.總結(jié)

餓漢模式:無法對(duì)instance實(shí)例進(jìn)行延遲加載
懶漢模式:多線程下無法保證唯一性
線程安全的懶漢模式:使用synchronized影響性能
DCL模式:被JVM的即時(shí)編譯器的指令重排序因素影響,可使用volatile解決
靜態(tài)內(nèi)部類/枚舉模式:延遲加載/線程安全/效率保證
所以亥贸,推薦在項(xiàng)目中使用靜態(tài)內(nèi)部類和枚舉去實(shí)現(xiàn)單例躬窜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市炕置,隨后出現(xiàn)的幾起案子荣挨,更是在濱河造成了極大的恐慌男韧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件默垄,死亡現(xiàn)場(chǎng)離奇詭異此虑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)口锭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門寡壮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人讹弯,你說我怎么就攤上這事况既。” “怎么了组民?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵棒仍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我臭胜,道長(zhǎng)莫其,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任耸三,我火速辦了婚禮乱陡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仪壮。我一直安慰自己憨颠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布积锅。 她就那樣靜靜地躺著爽彤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缚陷。 梳的紋絲不亂的頭發(fā)上适篙,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音箫爷,去河邊找鬼嚷节。 笑死,一個(gè)胖子當(dāng)著我的面吹牛虎锚,可吹牛的內(nèi)容都是我干的硫痰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼翁都,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼碍论!你這毒婦竟也來了根吁?” 一聲冷哼從身側(cè)響起倡怎,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤梦湘,失蹤者是張志新(化名)和其女友劉穎魁兼,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藏研,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡敬矩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蠢挡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弧岳。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖业踏,靈堂內(nèi)的尸體忽然破棺而出禽炬,到底是詐尸還是另有隱情,我是刑警寧澤勤家,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布腹尖,位于F島的核電站,受9級(jí)特大地震影響伐脖,放射性物質(zhì)發(fā)生泄漏热幔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一讼庇、第九天 我趴在偏房一處隱蔽的房頂上張望绎巨。 院中可真熱鬧,春花似錦蠕啄、人聲如沸场勤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽却嗡。三九已至,卻和暖如春嘹承,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背如庭。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工叹卷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坪它。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓骤竹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親往毡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蒙揣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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