創(chuàng)建型模式(二):?jiǎn)卫J?/h1>

介紹:

單例模式是一種創(chuàng)建型模式碴开。它保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)魏宽。

類圖:

img

單例模式UML類圖.png

Singleton(單例類):定義一個(gè)getInstance操作塔插,允許客戶訪問它的唯一實(shí)例桐经,getInstance是一個(gè)靜態(tài)方法,主要負(fù)責(zé)創(chuàng)建自己的唯一實(shí)例主到。

用法:

? 確保某個(gè)類有且只有一個(gè)對(duì)象時(shí)茶行。

個(gè)人理解:
? 創(chuàng)建一個(gè)對(duì)象需要消耗過多資源時(shí)(IO操作、訪問數(shù)據(jù)庫(kù)等)
? 工具類登钥、幫助類( 應(yīng)用程序的日志應(yīng)用畔师、接入第三方SDK等)
? 頻繁實(shí)例化然后銷毀的對(duì)象(日志、網(wǎng)絡(luò)訪問等)

例子:

單例模式是最常用的一個(gè)設(shè)計(jì)模式牧牢,常見的寫法有幾種:餓漢式茉唉、懶漢式固蛾、懶漢式同步鎖雙重校驗(yàn)鎖度陆、靜態(tài)內(nèi)部類的單例模式艾凯。

1、餓漢式(線程安全懂傀、沒有懶加載)
public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}

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

特點(diǎn):直接在應(yīng)用加載時(shí)初始化趾诗,但會(huì)浪費(fèi)內(nèi)存。
解析:在類初始化時(shí)已經(jīng)初始化實(shí)例蹬蚁,線程安全的恃泪。

2、懶漢式(線程不安去犀斋,有懶加載)
public class Singleton{
    private static Singleton instance = null;
    private Singleton(){}

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

}

特點(diǎn):單例的初始化操作贝乎,延遲到需要的時(shí)候才進(jìn)行,但線程不安全叽粹。
解析:在調(diào)用getInstance()方法時(shí)才實(shí)例化览效,達(dá)到延遲加載的效果。

3虫几、懶漢式同步鎖(線程安全锤灿,有懶加載)
public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
 
    public static Singleton getInstance() {
        synchronized (Singleton.class) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
        return instance;
    }

}

特點(diǎn):使用同步鎖synchronized保證多線程情況下單例對(duì)象的唯一性,但很多不必要的同步會(huì)影響性能辆脸。
解析:synchronized會(huì)造成不必要的同步開銷但校,很多情況也不需要同步,不推薦使用啡氢。

4状囱、雙重校驗(yàn)鎖(線程安全,有懶加載)
public class Singleton {
    private static volatile Singleton instance = null;
    private Singleton(){}
 
    public static Singleton getInstance() {
        if (instance == null) {  //此處避免了不必要的同步
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
 
        return instance;
    }
}

特點(diǎn):線程安全倘是,避免了不必要的同步浪箭,但高并發(fā)環(huán)境下小概率會(huì)有DCL失效問題。
解析:instance = new Singleton();語(yǔ)句辨绊,大概做了3件事情:
(1)奶栖、給Singleton的實(shí)例分配內(nèi)存
(2)、調(diào)用Singleton()的構(gòu)造函數(shù)
(3)门坷、將instance對(duì)象指向分配的內(nèi)存空間(instance不是null了)

但由于java編譯器允許處理器亂序執(zhí)行宣鄙,執(zhí)行順序可能是 (1)-(2)-(3)或者(1)-(3)-(2)。如果是后者情況默蚌,切換到另外的線程中冻晤,instance已經(jīng)不是null了,線程B直接取走instance绸吸,再使用時(shí)就會(huì)出錯(cuò)鼻弧,這就是DCL失效的問題了设江。

5、靜態(tài)內(nèi)部類的單例模式(線程安全攘轩,有懶加載)
public class Singleton{

    private Singleton(){}

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

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

}

特點(diǎn):懶加載的同時(shí)保證線程安全,推薦使用
解析:為什么會(huì)線程安全度帮?類的構(gòu)造器<clinit>()方法在多線程環(huán)境中被正確地加載歼捏,同步,如果多個(gè)線程同時(shí)去初始化一個(gè)類笨篷,那么只有一個(gè)線程去執(zhí)行這個(gè)類的瞳秽,其他線程都需要阻塞等待,直到活動(dòng)線程執(zhí)行<clinit>()方法完畢率翅。

總結(jié):

上述幾種做法已經(jīng)滿足了絕大部分的需求练俐,還有一些其它做法可以參考其它資料哈。

另外冕臭,單例模式需要注意內(nèi)存泄漏的問題腺晾,當(dāng)一個(gè)對(duì)象已經(jīng)不需要再使用本該被回收時(shí),另外一個(gè)正在使用的對(duì)象持有它的引用從而導(dǎo)致它不能被回收浴韭,產(chǎn)生了內(nèi)存泄漏。

感謝您的閱讀~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末脯宿,一起剝皮案震驚了整個(gè)濱河市念颈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌连霉,老刑警劉巖榴芳,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異跺撼,居然都是意外死亡窟感,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門歉井,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柿祈,“玉大人,你說我怎么就攤上這事哩至□锖浚” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵菩貌,是天一觀的道長(zhǎng)卢佣。 經(jīng)常有香客問我,道長(zhǎng)箭阶,這世上最難降的妖魔是什么虚茶? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任戈鲁,我火速辦了婚禮,結(jié)果婚禮上嘹叫,老公的妹妹穿的比我還像新娘婆殿。我一直安慰自己,他們只是感情好待笑,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布鸣皂。 她就那樣靜靜地躺著,像睡著了一般暮蹂。 火紅的嫁衣襯著肌膚如雪寞缝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天仰泻,我揣著相機(jī)與錄音荆陆,去河邊找鬼。 笑死集侯,一個(gè)胖子當(dāng)著我的面吹牛被啼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棠枉,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼浓体,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了辈讶?” 一聲冷哼從身側(cè)響起命浴,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贱除,沒想到半個(gè)月后生闲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡月幌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年碍讯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扯躺。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捉兴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出录语,到底是詐尸還是另有隱情轴术,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布钦无,位于F島的核電站逗栽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏失暂。R本人自食惡果不足惜彼宠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一鳄虱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凭峡,春花似錦拙已、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至索昂,卻和暖如春建车,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背椒惨。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工缤至, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人康谆。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓领斥,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親沃暗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子月洛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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