2--∞:單例模式(Singleton Pattern)

前言

此篇文章只是本人學習 單列模式(Singleton Pattern) 使用的筆記违帆,如有雷同几于,純屬緣分!

什么是單例黎侈?

單例模式(Singleton Pattern):確保某一個類只有一個實例馆蠕,并提供該實例的全局訪問,其構(gòu)造函數(shù)私有化是尔。它是 Java 中最簡單的設(shè)計模式(Design Pattern)殉了。

設(shè)計模式(Design Pattern):前人對特定問題經(jīng)過無數(shù)次的經(jīng)驗總結(jié)之后 ,提出的能夠解決它的優(yōu)雅的方案拟枚。它不是一種技術(shù)與方法薪铜,而是一種思想!

本質(zhì):

控制實例數(shù)量

三大要點:

線程安全
延遲加載
序列化與反序列化安全

單例的幾種寫法

1.餓漢式
public class Singleton {
    //上去就是干恩溅,直接實例化
    private static Singleton instances = new Singleton();
    //私有化構(gòu)造函數(shù)隔箍,阻止實例化對象
    private Singleton() {}
    //直接返回已經(jīng)實例化了的對象
    public static Singleton getInstances() {
        return instances;
    }
    public void doSomething() {
        //doSomething....
    }
}

餓漢式 這種實現(xiàn)單例方法是最簡單粗暴的,它在類開始加載時就初始化了(但浪費內(nèi)存)脚乡,而且在多線程中是安全的蜒滩,是典型的空間換時間。如果單例對象初始化非衬坛恚快俯艰,而且占用內(nèi)存非常小的時候,用這種方式是比較合適的锌订,可以直接在應用啟動時加載并初始化竹握。

2.懶漢式,線程不安全
public class Singleton {
    private static Singleton instances = null;
    private Singleton() {}
    //如果發(fā)現(xiàn)沒有實例對象辆飘,就構(gòu)造一個;如果有實例對象啦辐,直接返回
    public static Singleton getInstances() {
        if (instances == null) {
            instances = new Singleton();
        }
        return instances;
    }
    public void doSomething() {
        //doSomething
    }
}

懶漢式 就是將單例的初始化操作,延遲加載 到需要的時候才進行蜈项,這樣做在某些場合中有很大用處昧甘。比如某個單例用的次數(shù)不是很多,但是這個單例提供的功能又非常復雜战得,而且加載和初始化要消耗大量的資源,這個時候使用懶漢式就是非常不錯的選擇庸推。但它在 多線程中不安全(比如常侦,有兩個線程,一個是線程 A贬媒,一個是線程 B聋亡,它們同時調(diào)用 getInstances 方法,就可能導致并發(fā)問題)际乘,是典型的時間換空間坡倔。

3.懶漢式,線程安全
public class Singleton {
    private static Singleton instances = null;
    private Singleton() {}
    public static Singleton getInstances() {
        //加入同步鎖 synchronized
        synchronized (Singleton.class) {
            if (instances == null) {
                instances = new Singleton();
            }
            return instances;
        }
    }
    public void doSomething() {
        //doSomething
    }
}

這種是最常見的解決同步問題的一種方式,使用同步鎖 **synchronized (Singleton.class) **防止多線程同時進入造成 getInstances 被多次實例化罪塔。

4.懶漢式投蝉,雙重校驗鎖
public class Singleton {
    // 對保存實例的變量添加 volitile 的修飾
    private volatile static Singleton instances = null;
    private Singleton(){}
    public static Singleton getInstances(){
        //先檢查實例是否存在,如果不存在才進入下面的同步塊
        if(instances == null){
            //同步塊征堪,線程安全的創(chuàng)建實例
            synchronized (Singleton.class) {
                //再次檢查實例是否存在瘩缆,如果不存在才真正的創(chuàng)建實例
                if (instances == null){
                    instances = new Singleton();
                }
            }
        }
        return instances;
    }
    public void doSomething() {
        //doSomething
    }
}

雙重校驗鎖 指的是:并不是每次進入 getInstances 方法都需要同步,而是先不同步佃蚜,進入方法過后庸娱,先檢查實例是否存在,如果不存在才進入下面的同步塊谐算,這是第一重檢查熟尉。進入同步塊后,再次檢查實例是否存在洲脂,如果不存在斤儿,就在同步的情況下創(chuàng)建一個實例。這是第二重檢查腮考。

雙重加鎖機制的實現(xiàn)會使用一個關(guān)鍵字 volatile 雇毫,它的意思是:被 volatile 修飾的變量的值,將不會被本地線程緩存踩蔚,所有對該變量的讀寫都是直接操作共享內(nèi)存棚放,從而確保多個線程能正確的處理該變量。

5.靜態(tài)內(nèi)部類
public class Singleton {
    //類級的內(nèi)部類馅闽,也就是靜態(tài)類的成員式內(nèi)部類飘蚯,該內(nèi)部類的實例與外部類的實例
    //沒有綁定關(guān)系,而且只有被調(diào)用時才會裝載福也,從而實現(xiàn)了延遲加載
    private static class SingletonHolder {
        //靜態(tài)初始化器局骤,由JVM來保證線程安全
        private static Singleton instances = new Singleton();
    }
    private Singleton() {}
    public static Singleton getInstances() {
        return SingletonHolder.instances;
    }
    public void doSomething() {
        //doSomething
    }
}

這樣實現(xiàn)出來的單例類就是線程安全的,而且使用起來非常簡潔暴凑。

6.枚舉類型單例模式
public enum Singleton{
    //定義一個枚舉的元素峦甩,它就是Singleton的一個實例
    instance;
    public void doSomething(){
        // do something ...
    }    
}

這種方法是根據(jù) Effective Java 書中的說法,默認枚舉實例的創(chuàng)建是 線程安全 的.(創(chuàng)建枚舉類的單例在 JVM 層面也是能保證線程安全的), 所以不需要擔心線程安全的問題现喳,所以理論上枚舉類來實現(xiàn)單例模式是最簡單的方式凯傲。

總結(jié)

以上就是 單例模式 的幾種寫法。分別是餓漢嗦篱、懶漢冰单、同步鎖雙重校驗鎖灸促、靜態(tài)內(nèi)部類枚舉诫欠。我們可以根據(jù)不同的場景選擇最喜歡的一種單例模式吧涵卵!

如何使用

當需要控制一個類的實例只能有一個,而且客戶只能從一個全局訪問點訪問它時荒叼,可以選用單例模式轿偎,這些功能恰好是單例模式要解決的問題

番外閱讀

單例模式的一些注意點

參考

ANDROID設(shè)計模式之單例模式
設(shè)計模式干貨系列:(四)單例模式【學習難度:★☆☆☆☆,使用頻率:★★★★☆】

                                        -- 默默的劃水ing--
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甩挫,一起剝皮案震驚了整個濱河市贴硫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伊者,老刑警劉巖英遭,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異亦渗,居然都是意外死亡挖诸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門法精,熙熙樓的掌柜王于貴愁眉苦臉地迎上來多律,“玉大人,你說我怎么就攤上這事搂蜓±擒瘢” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵帮碰,是天一觀的道長相味。 經(jīng)常有香客問我,道長殉挽,這世上最難降的妖魔是什么丰涉? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮斯碌,結(jié)果婚禮上一死,老公的妹妹穿的比我還像新娘。我一直安慰自己傻唾,他們只是感情好投慈,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冠骄,像睡著了一般伪煤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猴抹,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音锁荔,去河邊找鬼蟀给。 笑死蝙砌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的跋理。 我是一名探鬼主播择克,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼前普!你這毒婦竟也來了肚邢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拭卿,失蹤者是張志新(化名)和其女友劉穎骡湖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峻厚,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡响蕴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惠桃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浦夷。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辜王,靈堂內(nèi)的尸體忽然破棺而出劈狐,到底是詐尸還是另有隱情,我是刑警寧澤呐馆,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布肥缔,位于F島的核電站,受9級特大地震影響摹恰,放射性物質(zhì)發(fā)生泄漏辫继。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一俗慈、第九天 我趴在偏房一處隱蔽的房頂上張望姑宽。 院中可真熱鬧,春花似錦闺阱、人聲如沸炮车。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘦穆。三九已至,卻和暖如春赊豌,著一層夾襖步出監(jiān)牢的瞬間扛或,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工碘饼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留熙兔,地道東北人悲伶。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像住涉,于是被迫代替她去往敵國和親麸锉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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