設(shè)計模式——單例模式

定義

確保某個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例薪捍。

創(chuàng)建方式

/**
 * 餓漢式
 * 
 * 類加載時笼痹,實例就跟創(chuàng)建初始化了,所以是線程安全 (類加載的過程就是線程安全的)
 * 不支持懶加載
 */
public class SingleHunger {
    private static SingleHunger instance = new SingleHunger();

    private SingleHunger() {
    }

    public static SingleHunger getInstance() {
        return instance;
    }
}
/**
 * 懶漢式
 *
 * 線程安全
 * 因為在 getInstance方法加了個鎖飘诗,那么每次在使用這個單例時与倡,我們都會調(diào)用getInstance方法,
 * 那么也就每次都需要加鎖昆稿、釋放鎖了纺座。 如果單例使用比較頻繁的話,這種方式就不是很好了
 */
public class SingleLazy {

    private SingleLazy instance;

    private SingleLazy(){
    }

    private synchronized SingleLazy getInstance(){
        if (instance == null)
            instance = new SingleLazy();
        return instance;
    }
}
/**
 * 雙重校驗
 */
public class SingleDoubleCheck {
    private volatile SingleDoubleCheck instance;

    private SingleDoubleCheck(){
    }

    private SingleDoubleCheck getInstance(){
        if (instance == null){
            synchronized (SingleDoubleCheck.class){
                if (instance == null){
                    instance = new SingleDoubleCheck();
                }
            }
        }
        return instance;
    }
}

雙重鎖校驗為什么instance要使用關(guān)鍵字`volatile`
因為 `instance = new Single()` 這句賦值代碼不是原子操作溉潭,這句代碼包含以下3個步驟
1. 給 `new Single()`所即將創(chuàng)建的對象分配內(nèi)存空間
2. 初始化對象 净响,即執(zhí)行`new Single()`構(gòu)造方法
3. 把創(chuàng)建對象的內(nèi)存空間地址賦值給`instance`

編譯器指令重排可能會把2、3步的順序顛倒喳瓣,這樣的話馋贤,`Single`對象還沒真正初始化,但內(nèi)存地址已經(jīng)被賦值給了變量`instance`畏陕,
這樣其他線程判斷`instance`不為空配乓,就直接拿去使用了,但instance其實并沒有真正的被初始化惠毁,也就出現(xiàn)了問題犹芹。
所以使用關(guān)鍵字`volatile`來修飾`instance`禁止指令重排。

`volatile` 解決有序性:
采用部分禁止指令重排鞠绰。
對于volatile修飾的變量執(zhí)行寫操作腰埂,禁止位于其前面的讀寫操作與其進行重排序;
對于volatile修飾的變量執(zhí)行讀操作蜈膨,禁止位于其后面的讀寫操作與其進行重排序
這樣屿笼,步驟3是對`instance`進行寫操作牺荠,根據(jù)`volatile`指令禁止重排規(guī)則,
位于其前面的讀寫操作禁止與其進行重排序驴一,那么步驟2也就不能和步驟3指令重排序了休雌。

/**
 * 靜態(tài)內(nèi)部類
 */
public class SingleStatic {

    private SingleStatic() {
    }

    public static class SingleHandler {
        private static final SingleStatic instance = new SingleStatic();
    }

    public static SingleStatic getInstance() {
        return SingleHandler.instance;
    }
}

為什么這種方式創(chuàng)建的單例是支持懶加載的?
  答:靜態(tài)變量的初始化是在類加載時蛔趴,類是在用到它的時候才被加載的挑辆。
     所以instance真正初始化  時機是在調(diào)用getInstance方法時。
     而且靜態(tài)變量只會初始化一次孝情,所以我們后續(xù)調(diào)用getInstance得到的是同一個實例。

為什么是線程安全的洒嗤?
  答:因為getInstance整個流程都是在類加載過程中完成的箫荡,而類的加載機制是線程安全的。

不用靜態(tài)內(nèi)部類可以嗎渔隶?
  答:如果是普通內(nèi)部類的話羔挡,是不可以聲明靜態(tài)變量的。
     如果instance不是靜態(tài)的间唉,那么就無法在類加載過程中初始化绞灼,也就無法保證線程安全了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呈野,一起剝皮案震驚了整個濱河市低矮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌被冒,老刑警劉巖军掂,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昨悼,居然都是意外死亡蝗锥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門率触,熙熙樓的掌柜王于貴愁眉苦臉地迎上來终议,“玉大人,你說我怎么就攤上這事葱蝗⊙ㄕ牛” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵垒玲,是天一觀的道長陆馁。 經(jīng)常有香客問我,道長合愈,這世上最難降的妖魔是什么叮贩? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任击狮,我火速辦了婚禮,結(jié)果婚禮上益老,老公的妹妹穿的比我還像新娘彪蓬。我一直安慰自己,他們只是感情好捺萌,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布档冬。 她就那樣靜靜地躺著,像睡著了一般桃纯。 火紅的嫁衣襯著肌膚如雪酷誓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天态坦,我揣著相機與錄音盐数,去河邊找鬼。 笑死伞梯,一個胖子當著我的面吹牛玫氢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谜诫,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼漾峡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喻旷?” 一聲冷哼從身側(cè)響起生逸,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掰邢,沒想到半個月后牺陶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡辣之,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年掰伸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怀估。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡狮鸭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出多搀,到底是詐尸還是另有隱情歧蕉,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布康铭,位于F島的核電站惯退,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏从藤。R本人自食惡果不足惜催跪,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一锁蠕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懊蒸,春花似錦荣倾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至通危,卻和暖如春铸豁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黄鳍。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工推姻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人框沟。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像增炭,于是被迫代替她去往敵國和親忍燥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 目錄 本文的結(jié)構(gòu)如下: 什么是單例模式 為什么要用該模式 模式的結(jié)構(gòu) 代碼示例 優(yōu)點和缺點 適用環(huán)境 模式應用 總...
    w1992wishes閱讀 390評論 1 2
  • 單例模式 介紹 為了節(jié)約系統(tǒng)資源隙姿,有時需要確保系統(tǒng)中某個類只有唯一一個實例梅垄,當這個唯一實例創(chuàng)建成功之后,我們無法再...
    666真666閱讀 346評論 0 6
  • 我是皇帝我獨苗 原書通過皇帝這一角色來解釋何為單例模式输玷,可以說是很形象队丝。自從秦始皇確立了皇帝這個位置后,同一時期基...
    stayiwithime閱讀 254評論 0 0
  • 一、介紹: 單例模式是應用最廣的模式之一赔嚎;在應用這個模式時膘盖,單例對象的類必須保證只有一個實例的存在;許多時候尤误,整個...
    BrightLight閱讀 295評論 0 0
  • 1. 單例模式 確保某一個對象只有一個實例侠畔,而且自行實例化并向整個程序提供這個實例。 優(yōu)點 由于單例模式在內(nèi)存中只...
    Mr希靈閱讀 6,396評論 0 5