java設(shè)計模式之單例模式

前幾天看到一個問題议慰,問單例模式有幾種實現(xiàn)方式速址,由此今天來說一下這個問題龄糊。

首先說說什么是單例模式逆粹,它是指JAVA類有且只有一個全局訪問點,保證該類只創(chuàng)建一個實例炫惩。單例模式有三個基本的要點:

1僻弹、該類只有一個實例。

2他嚷、這個實例必須是自行創(chuàng)建蹋绽。

3、必須自行為整個系統(tǒng)提供該實例的訪問筋蓖。

一般情況下卸耘,單例模式分區(qū)餓漢模式懶漢模式;餓漢模式會在類初始化的時候就開辟一塊內(nèi)存空間粘咖,它保證了多線程下實例的唯一性蚣抗,并且效率非常高;但是缺點在于當(dāng)類的成員比較多或者變量比較大的時候就開辟了空間對資源的消耗就比較大瓮下。為了避免餓漢模式的這個問題翰铡,懶漢模式會在系統(tǒng)使用到這個類是才去創(chuàng)建這個對象。

常規(guī)實現(xiàn)

餓漢模式:
public final class Singleton {
    /**
     * 自行創(chuàng)建私有實例
     */
    private static Singleton instance = new Singleton();
    /**
     * 私有構(gòu)造
     */
    private Singleton() {
    }
    /**
     * 提供公有的全局訪問點
     * @return
     */
    public static Singleton getInstance() {
        return instance;
    }
}
懶漢模式:
public final class Singleton {
    /**
     * 自行創(chuàng)建私有實例
     */
    private static Singleton instance = null;
    /**
     * 私有構(gòu)造
     */
    private Singleton() {
    }
    /**
     * 提供公有的全局訪問點
     * @return
     */
    public static Singleton getInstance() {
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}

以上代碼是餓漢模式和懶漢模式的常用實現(xiàn)代碼讽坏;但是以上懶漢模式是存在問題的锭魔,試想,在多線程的場景下運行震缭,同時執(zhí)行到這段代碼時赂毯,可能會實例化多個實例战虏。
這時候拣宰,我們可以添加synchronized來同步鎖修飾getInstance方法党涕,保證其只被實例化一次

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

但是,這樣做了之后還是有問題的巡社,使用同步鎖會帶來鎖競爭膛堤,增加系統(tǒng)的性能開銷,這時候可以考慮將synchronized添加在if條件中:

    public static Singleton getInstance() {
        if(instance==null){
            synchronized(Singleton.class){
                instance = new Singleton();
            }
        }
        return instance;
    }

這樣晌该,感覺是完美了肥荔;但如果兩個線程同時進(jìn)入了if條件里面,雖然有同步鎖朝群,但是進(jìn)入到條件里面的線程依然會依次獲取鎖創(chuàng)建對象燕耿,然后再釋放同步鎖,所以在if條件里面還需要添加if條件的判斷

    public static  Singleton getInstance() {
        if(instance==null){
            synchronized(Singleton.class){
                if(instance==null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

這樣姜胖,通過synchronized+兩次if就實現(xiàn)了一個穩(wěn)定的單例模式結(jié)構(gòu)誉帅,但是此種結(jié)構(gòu)比較復(fù)雜,有沒有簡化一點的呢右莱?

內(nèi)部類實現(xiàn)

餓漢模式中蚜锨,使用static修飾的instance,所以類在初始化完成就已經(jīng)被收集到類構(gòu)造器中了慢蜓。在多線程情況下亚再,JVM會保證只有一個線程能執(zhí)行這個方法,其他線程都會被阻塞等待晨抡。這種方式保證了內(nèi)存的可見性氛悬、順序性、原子性耘柱。
如果通過一個內(nèi)部類來完成成員的實例化圆雁,則也可以避免多線程重復(fù)創(chuàng)建實例的情況:

public final class Singleton {
    /**
     * 私有構(gòu)造
     */
    private Singleton() {
    }
    /**
     * 提供公有的全局訪問點
     * @return
     */
    public static  Singleton getInstance() {
        return InsideSingleton.instance;
    }
    /**
     * 實例
     */
    public static class InsideSingleton {
        private static Singleton instance = new Singleton();
    } 
}

枚舉實現(xiàn)

相較于餓漢模式懶漢模式,枚舉是實現(xiàn)方式就會更加簡潔

public final class Singleton {
    /**
     * 私有構(gòu)造
     */
    private Singleton() {
    }
    /**
     * 提供公有的全局訪問點
     * @return
     */
    public static Singleton getInstance() {
        return SinletonEnum.SINLETON.getInstance();
    }
    /**
     * 定義單例枚舉
     */
    private enum SinletonEnum {
        SINLETON;
        private Singleton singleton;

        SinletonEnum() {
            singleton = new Singleton();
        }
        /**
         * 構(gòu)建實例
         */
        public Singleton getInstance() {
            return singleton;
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帆谍,一起剝皮案震驚了整個濱河市伪朽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汛蝙,老刑警劉巖烈涮,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異窖剑,居然都是意外死亡坚洽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門西土,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讶舰,“玉大人,你說我怎么就攤上這事√纾” “怎么了般甲?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鹅颊。 經(jīng)常有香客問我敷存,道長,這世上最難降的妖魔是什么堪伍? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任锚烦,我火速辦了婚禮,結(jié)果婚禮上帝雇,老公的妹妹穿的比我還像新娘涮俄。我一直安慰自己,他們只是感情好尸闸,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布禽拔。 她就那樣靜靜地躺著,像睡著了一般室叉。 火紅的嫁衣襯著肌膚如雪睹栖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天茧痕,我揣著相機(jī)與錄音野来,去河邊找鬼。 笑死踪旷,一個胖子當(dāng)著我的面吹牛曼氛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播令野,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼舀患,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了气破?” 一聲冷哼從身側(cè)響起聊浅,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎现使,沒想到半個月后低匙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡碳锈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年顽冶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片售碳。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡强重,死狀恐怖绞呈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情间景,我是刑警寧澤佃声,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站拱燃,受9級特大地震影響秉溉,放射性物質(zhì)發(fā)生泄漏力惯。R本人自食惡果不足惜碗誉,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望父晶。 院中可真熱鬧哮缺,春花似錦、人聲如沸甲喝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽埠胖。三九已至糠溜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間直撤,已是汗流浹背非竿。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留谋竖,地道東北人红柱。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像蓖乘,于是被迫代替她去往敵國和親锤悄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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