java單例設(shè)計模式

1.應(yīng)用場景:

當(dāng)需要保證類在內(nèi)存中的對象唯一性些椒,可以使用單例模式,
不想創(chuàng)建多個實例浪費資源掸刊,或者避免多個實例由于多次調(diào)用
而出現(xiàn)錯誤免糕。一般寫工具類,線程池忧侧,緩存石窑,數(shù)據(jù)庫等可以用到。

2.各種各樣的單例寫法

1.餓漢模式

public class Singleton {
    
    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

獲取單例對象:Singleton instace = Singleton.getInstance();
優(yōu)點:類加載的時候就完成實例化蚓炬,避免線程同步問題
缺點:由于在類加載的時候就進行了實例化松逊,所以沒有達到Lazy Loading(懶加載)
的效果,即使我們沒用到這個實例肯夏,但是他還是會加載经宏,從而造成內(nèi)存浪費(可以忽略犀暑,
最常用的一種)。

2.懶漢模式(線程不安全)

public class Singleton {
    
    private static Singleton instance = null;

    private Singleton() {
    }

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

盡管達到了懶加載烁兰,但是卻存在線程安全問題耐亏,比如有兩個線程,剛好都
執(zhí)行完if(instance == null)缚柏,接著準(zhǔn)備執(zhí)行instance = new Singleton()
語句苹熏,這樣的結(jié)果會導(dǎo)致我們實例化了兩個Singleton對象,這就是懶漢單例
模式可能會引發(fā)的線程安全問題币喧,解決這個方法轨域,我們可以對getInstance方法加鎖。

3.懶漢模式(線程安全杀餐,但效率低)

public class Singleton {
    
    private static Singleton instance = null;

    private Singleton() {
    }

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

盡管保證了線程安全干发,但是每個線程在想要獲得實例時,執(zhí)行g(shù)etInstance()
方法都需要進行同步史翘,而實例化代碼只需執(zhí)行一次就夠了枉长,后面獲取該實例,
直接return即可琼讽,方法進行同步效率太低必峰,需要改進。還有一種寫法是:
synchronized (Singleton.class) { instance = new Singleton(); }
這樣一樣是線程不安全的钻蹬,如果你想使用懶漢模式的話吼蚁,推薦使用下面的:
DCL單例(雙重檢查鎖定)。

4.懶漢模式雙重校驗鎖

public class Singleton {
    
    private static volatile Singleton instance = null;

    private Singleton() {
    }

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

代碼中進行了兩次if檢查问欠,這樣就可以保證線程安全肝匆,初始化一次后,
后面再次訪問時顺献,if檢查旗国,直接return 實例化對象。volatile是1.5后
引入的注整,volatile關(guān)鍵字會屏蔽Java虛擬機所做的一些代碼優(yōu)化能曾,會導(dǎo)
致系統(tǒng)運行效率降低,而更好的寫法是使用靜態(tài)內(nèi)部類來實現(xiàn)單例肿轨!

5.靜態(tài)內(nèi)部類實現(xiàn)單例模式

public class Singleton {

    private Singleton() {
    }

    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
}

和餓漢式類似寿冕,兩者都是通過類裝載機制來保證初始化實例
的時候只有一個線程,從而避免線程安全問題萝招,餓漢式的
Singleton類被加載蚂斤,就會實例化,而靜態(tài)內(nèi)部類這種槐沼,
當(dāng)Singleton類被加載時曙蒸,不會立即實例化捌治,調(diào)用getInstance方法,
才會裝載SingletonHolder類纽窟,從而完成Singleton的實例化肖油。

6.枚舉實現(xiàn)單例模式

public enum SingletonEnum {
    INSTANCE;
    private Singleton instance;
    SingletonEnum() { 
        instance = new Singleton()
    }
    public Singleton getInstance() {
        return instance;
    }
}

訪問方式:SingletonEnum.INSTANCE.method();
INSTANCE即為SingletonEnum類型的引用,得到它就可以調(diào)用
枚舉中的方法臂港。既避免了線程安全問題森枪,還能防止反序列化
重新創(chuàng)建新的對象,但是失去了類的一些特性审孽,沒有延時加載县袱,
推薦使用。

7.使用容器實現(xiàn)單例模式

public class SingletonManager {
    private static Map<String,Object> objMap = new HashMap<String,Object>();
    private Singleton() { }
    public static void registerService(String key,Object instance) {
        if(!objMap.containsKey(key)) {
            objMap.put(key,instance);
        }
    }
    public static Object getService(String key) {
        return objMap.get(key);
    }
}

將多種單例類型注入到一個統(tǒng)一的管理類中佑力,在使用時根據(jù)key獲取對象
對應(yīng)類型的對象式散。這種方式使得我們可以管理多種類型的單例,并且在使
用時可以通過統(tǒng)一的接口進行獲取操作打颤,降低了用戶的使用成本暴拄,也對用
戶隱藏了具體實現(xiàn),降低了耦合度编饺。


優(yōu)缺點

優(yōu)點:保持類對象唯一性乖篷,對于頻繁創(chuàng)建和銷毀的對象可以提高性能。
缺點:擴展困難透且,單例的方法無法生成子類對象撕蔼,要擴展的話基本要重寫這個類。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末石蔗,一起剝皮案震驚了整個濱河市罕邀,隨后出現(xiàn)的幾起案子畅形,更是在濱河造成了極大的恐慌养距,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件日熬,死亡現(xiàn)場離奇詭異棍厌,居然都是意外死亡,警方通過查閱死者的電腦和手機竖席,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門耘纱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人毕荐,你說我怎么就攤上這事束析。” “怎么了憎亚?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵员寇,是天一觀的道長弄慰。 經(jīng)常有香客問我,道長蝶锋,這世上最難降的妖魔是什么陆爽? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮扳缕,結(jié)果婚禮上慌闭,老公的妹妹穿的比我還像新娘。我一直安慰自己躯舔,他們只是感情好驴剔,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粥庄,像睡著了一般仔拟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上飒赃,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天利花,我揣著相機與錄音,去河邊找鬼载佳。 笑死炒事,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔫慧。 我是一名探鬼主播挠乳,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姑躲!你這毒婦竟也來了睡扬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤黍析,失蹤者是張志新(化名)和其女友劉穎卖怜,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阐枣,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡马靠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔼两。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甩鳄。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖额划,靈堂內(nèi)的尸體忽然破棺而出妙啃,到底是詐尸還是另有隱情,我是刑警寧澤俊戳,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布揖赴,位于F島的核電站茁瘦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏储笑。R本人自食惡果不足惜甜熔,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望突倍。 院中可真熱鬧腔稀,春花似錦、人聲如沸羽历。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秕磷。三九已至诵闭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澎嚣,已是汗流浹背疏尿。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留易桃,地道東北人褥琐。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像晤郑,于是被迫代替她去往敵國和親敌呈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349

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