你真的會(huì)用單例模式嗎

轉(zhuǎn)載請(qǐng)注明出處:http://tedyin.me/2016/03/13/singlton-pattern/

今天給大家介紹一下單例模式,就是這個(gè)出場率特別高的模式,是個(gè)程序員基本都用過他停忿,沒用過至少也都知道他。可是我們真的了解他嗎啼辣?

單例模式通常的實(shí)現(xiàn)方式分為以下兩種:

餓漢式

public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton newInstance(){
        return instance;
    }
    public void doSomething(){
        // Do something ...
     }
}

餓漢式是最簡單的實(shí)現(xiàn)方式协饲,這種實(shí)現(xiàn)方式適合那些在初始化時(shí)就要用到單例的情況,這種方式簡單粗暴凸主,如果不單例初始化非抽偃快,而且占用內(nèi)存非常小的時(shí)候這種方式是比較合適的,直接在應(yīng)用啟動(dòng)時(shí)加載并初始化旁舰。
但是锋华,如果單例初始化的操作耗時(shí)比較長而應(yīng)用對(duì)于啟動(dòng)速度又有要求,或者單例的占用內(nèi)存比較大箭窜,再或者單例只是在某個(gè)特定場景的情況下才會(huì)被使用毯焕,而一般情況下是不會(huì)使用時(shí),使用餓漢式的單例模式就是不合適的磺樱,這時(shí)候就需要用到懶漢式的方式去按需延遲加載單例纳猫。

懶漢式

public class Singleton{
    private static Singleton instance = null;    
    private Singleton(){}
    public static newInstance(){
        if(null == instance){
            instance = new Singleton();
        }
        return instance;
    }
    public void doSomething(){
        // Do something ...
    }
}

懶漢式餓漢式的最大區(qū)別就是將單例的初始化操作,延遲到需要的時(shí)候才進(jìn)行竹捉,這樣做在某些場合中有很大用處芜辕。比如某個(gè)單例用的次數(shù)不是很多,但是這個(gè)單例提供的功能又非常復(fù)雜块差,而且加載和初始化要消耗大量的資源物遇,這個(gè)時(shí)候使用懶漢式就是非常不錯(cuò)的選擇。

多線程下的單例模式

上面介紹了一些單例模式的基本應(yīng)用方法憾儒,但是上面所說的那些使用方式都是有一個(gè)隱含的前提询兴,那就是他們都是應(yīng)用在單線程條件下,一旦換成了多線程就有出錯(cuò)的風(fēng)險(xiǎn)起趾。
如果在多線程的情況下诗舰,餓漢式不會(huì)出現(xiàn)問題,因?yàn)镴VM只會(huì)加載一次單利類训裆,但是懶漢式可能就會(huì)出現(xiàn)重復(fù)創(chuàng)建單利對(duì)象的問題眶根。為什么會(huì)有這樣的問題呢?因?yàn)?code>懶漢式在創(chuàng)建單例時(shí)是 線程不安全的边琉,多個(gè)線程可能會(huì)并發(fā)調(diào)用他的newInstance方法導(dǎo)致多個(gè)線程可能會(huì)創(chuàng)建多份相同的單例出來属百。

那有沒有辦法,使餓漢式的單利模式也是線程安全的呢变姨?答案肯定是有的族扰,大家通常會(huì)使用加同步鎖的方式去實(shí)現(xiàn),但是這樣實(shí)現(xiàn)起來比較麻煩定欧。那么有沒有更好的實(shí)現(xiàn)方式呢渔呵?能問這個(gè)問題那必須是有的,否則就得打臉了砍鸠。 我們可以利用JVM的類加載機(jī)制去實(shí)現(xiàn)扩氢。在很多情況下JVM已經(jīng)為我們提供了同步控制,比如:

  • static{}區(qū)塊中初始化的數(shù)據(jù)
  • 訪問final字段時(shí)
  • ...
  • 等等

因?yàn)樵贘VM進(jìn)行類加載的時(shí)候他會(huì)保證數(shù)據(jù)是同步的爷辱,我們可以這樣實(shí)現(xiàn):

采用內(nèi)部類录豺,在這個(gè)內(nèi)部類里面去創(chuàng)建對(duì)象實(shí)例朦肘。這樣的話,只要應(yīng)用中不使用內(nèi)部類 JVM 就不會(huì)去加載這個(gè)單例類双饥,也就不會(huì)創(chuàng)建單例對(duì)象媒抠,從而實(shí)現(xiàn)懶漢式的延遲加載和線程安全。

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

public class Singleton{
    //內(nèi)部類兢哭,在裝載該內(nèi)部類時(shí)才會(huì)去創(chuàng)建單利對(duì)象
    private static class SingletonHolder{
        public static Singleton instance = new Singleton();
    }

    private Singleton(){}

    public static Singleton newInstance(){
        return SingletonHolder.instance;
    }

    public void doSomething(){
        //do something
    }
}

這樣實(shí)現(xiàn)出來的單例類就是線程安全的领舰,麻麻再也不用擔(dān)心我的單例不是單例了。

使用枚舉實(shí)現(xiàn)單例模式

除了上述的單例模式的實(shí)現(xiàn)方式外迟螺,我們還可以通過枚舉類來實(shí)現(xiàn)單利模式冲秽,這也是Effective Java中推薦的方式。

使用枚舉類型實(shí)現(xiàn)單例模式如下:

public enum Singleton{
    //定義一個(gè)枚舉的元素矩父,它就是Singleton的一個(gè)實(shí)例
    instance;

    public void doSomething(){
        // do something ...
    }    
}

用枚舉實(shí)現(xiàn)是不是更簡單呢锉桑?枚舉方式實(shí)現(xiàn)的單例模式也是線程安全的,所以大家不用擔(dān)心多線程問題窍株,可以大膽去用民轴。

以上就是單例模式的使用,現(xiàn)在完全可以說球订,你真的會(huì)用單例模式了后裸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市冒滩,隨后出現(xiàn)的幾起案子微驶,更是在濱河造成了極大的恐慌,老刑警劉巖开睡,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件因苹,死亡現(xiàn)場離奇詭異,居然都是意外死亡篇恒,警方通過查閱死者的電腦和手機(jī)扶檐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胁艰,“玉大人款筑,你說我怎么就攤上這事』茸拢” “怎么了醋虏?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長哮翘。 經(jīng)常有香客問我,道長毛秘,這世上最難降的妖魔是什么饭寺? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任阻课,我火速辦了婚禮,結(jié)果婚禮上艰匙,老公的妹妹穿的比我還像新娘限煞。我一直安慰自己,他們只是感情好员凝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布署驻。 她就那樣靜靜地躺著,像睡著了一般健霹。 火紅的嫁衣襯著肌膚如雪旺上。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天糖埋,我揣著相機(jī)與錄音宣吱,去河邊找鬼。 笑死瞳别,一個(gè)胖子當(dāng)著我的面吹牛征候,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祟敛,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疤坝,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了馆铁?” 一聲冷哼從身側(cè)響起跑揉,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎叼架,沒想到半個(gè)月后畔裕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乖订,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年扮饶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乍构。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡甜无,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哥遮,到底是詐尸還是另有隱情岂丘,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布眠饮,位于F島的核電站奥帘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏仪召。R本人自食惡果不足惜寨蹋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一靴跛、第九天 我趴在偏房一處隱蔽的房頂上張望吼具。 院中可真熱鬧傅联,春花似錦撒妈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秸讹,卻和暖如春檀咙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗦枢。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工攀芯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人文虏。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓侣诺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氧秘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子年鸳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • 一搔确、簡介: 單例模式:確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn). 單例模式是所有設(shè)計(jì)模式中最簡單的一個(gè),也是大...
    嘮嗑008閱讀 2,223評(píng)論 14 35
  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單、最易理解的設(shè)計(jì)模式灭忠,也因?yàn)樗暮啙嵰锥潘悖琼?xiàng)目中最...
    成熱了閱讀 4,253評(píng)論 4 34
  • 1 場景問題# 1.1 讀取配置文件的內(nèi)容## 考慮這樣一個(gè)應(yīng)用,讀取配置文件的內(nèi)容弛作。 很多應(yīng)用項(xiàng)目涕蜂,都有與應(yīng)用相...
    七寸知架構(gòu)閱讀 6,761評(píng)論 12 68
  • 1.單例模式概述 (1)引言 單例模式是應(yīng)用最廣的模式之一,也是23種設(shè)計(jì)模式中最基本的一個(gè)映琳。本文旨在總結(jié)通過Ja...
    曹豐斌閱讀 2,919評(píng)論 6 47
  • 細(xì)雨隨輕風(fēng)飄灑 黃葉攜水滴零落 思念的串珠綿柔有致 隔窗濺入心窩 雀歇屋檐下 車奔上高速 船留在水中 縱橫又寧靜 ...
    富景流觴閱讀 145評(píng)論 0 0