四種線程安全的單例模式寫法

單例模式(Singleton Pattern)作為Java設(shè)計模式之一,保證一個類僅有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn)。節(jié)省系統(tǒng)資源污抬,也適用于需要全局實(shí)例的場景。本文中介紹的四種單例模式皆為線程安全的寫法绳军。

1. 雙重檢查

public class MySingletonDoubleCheck {

    private static volatile MySingletonDoubleCheck singleton;

    private MySingletonDoubleCheck(){

    }

    private static MySingletonDoubleCheck getInstence(){
        if (singleton == null){
            synchronized (MySingletonDoubleCheck.class){
                if (singleton == null){
                    singleton = new MySingletonDoubleCheck();
                    return singleton;
                }
            }
        }
        return singleton;
    }
}

主要思想

定義了私有的靜態(tài)成員變量印机,volatile關(guān)鍵字可以禁止指令重排序,同時寫了一個私有的空的無參構(gòu)造方法防止強(qiáng)行使用new實(shí)例出一個變量门驾。synchronized (MySingletonDoubleCheck.class) 保證了當(dāng)同時有兩個線程想要實(shí)例化singleton變量時射赛,只會讓第一個線程實(shí)例化出變量,等到第二個線程進(jìn)入同步代碼塊時singleton變量已經(jīng)不為null了奶是。

volatile關(guān)鍵字的作用

volatile關(guān)鍵字的作用:在new出一個新對象的過程中楣责,計算機(jī)其實(shí)將其分成了3個步驟,第一步首先給singleton分配內(nèi)存聂沙,第二步隨后調(diào)用構(gòu)造方法初始化秆麸,第三步最后將singleton對象指向分配的內(nèi)存空間,此時singleton才不為null及汉【谌ぃ看起來順理成章,但是計算機(jī)為了提高效率坷随,在不影響結(jié)果的情況下房铭,可能會改變這三個步驟的順序,也就是說温眉,可能會先執(zhí)行第三步缸匪,再執(zhí)行第二步。注意芍殖,執(zhí)行完第三步之后豪嗽,singleton變量就已經(jīng)不是null了,但實(shí)際上它還沒有完成初始化,此時如果有第二個線程也想要得到單例對象龟梦,在第一次判斷singleton是否為null時就將尚未初始化的singleton返回隐锭,此時返回的singleton是不完整的。

優(yōu)點(diǎn)

延遲加載计贰,效率高钦睡。

缺點(diǎn)

代碼稍稍復(fù)雜了一點(diǎn),需要對鎖有一定理解躁倒,同時volatile也會影響一點(diǎn)點(diǎn)性能荞怒,但無傷大雅。

2. 餓漢式(靜態(tài)常量)

public class Singleton {
    
    private static final Singleton INSTANCE = new SingletonSample();

    private Singleton(){

    }

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

主要思想

采用靜態(tài)常量的方式實(shí)現(xiàn)單例秧秉,十分簡單褐桌,但依舊不能忘了寫一個私有無參構(gòu)造方法。

優(yōu)點(diǎn)

寫法簡單象迎。

缺點(diǎn)

在類裝載時就被實(shí)例化荧嵌,沒有達(dá)到懶加載(Lazy Loadind)的效果,有可能造成資源浪費(fèi)砾淌,比如從始至終都未使用過這個實(shí)例啦撮。

3. 靜態(tài)內(nèi)部類

public class SingletonStatic {

    private SingletonStatic(){

    }

    private static class SingletonInstance{
        private static final SingletonStatic SINGLETON_STATIC = new SingletonStatic();
    }

    public static SingletonStatic getInstance(){
        return SingletonInstance.SINGLETON_STATIC;
    }
}

主要思想

采用靜態(tài)內(nèi)部類的形式,思想與餓漢式類似汪厨,但靜態(tài)內(nèi)部類在類加載時不會被實(shí)例化赃春,只有在第一次調(diào)用getInstance()方法時才會加載,類的靜態(tài)屬性只會在第一次加載類的時候初始化劫乱,所以JVM保證了線程的安全性织中,在類進(jìn)行初始化時,別的線程無法干擾要拂。

優(yōu)點(diǎn)

延遲加載抠璃,效率高。

缺點(diǎn)

沒有什么缺點(diǎn)脱惰。

4. 枚舉+接口

  1. 以下為自定義接口:
public interface MySingleton {

    void doSomething();
}

  1. 利用枚舉實(shí)現(xiàn)單例模式:
public enum Singleton implements MySingleton {
   
    INSTANCE {
        @Override
        public void doSomething() {
            System.out.println("It is my singleton");
        }
    };

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

}

主要思想

借助JDK1.5中添加的枚舉來實(shí)現(xiàn)單例模式搏嗡。

優(yōu)點(diǎn)

不僅能避免多線程同步問題,而且還能防止反序列化重新創(chuàng)建新的對象拉一。

缺點(diǎn)

代碼較其他三種比較怪異采盒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蔚润,隨后出現(xiàn)的幾起案子磅氨,更是在濱河造成了極大的恐慌,老刑警劉巖嫡纠,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烦租,死亡現(xiàn)場離奇詭異延赌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)叉橱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門挫以,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窃祝,你說我怎么就攤上這事掐松。” “怎么了粪小?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵大磺,是天一觀的道長。 經(jīng)常有香客問我探膊,道長杠愧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任突想,我火速辦了婚禮殴蹄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猾担。我一直安慰自己,他們只是感情好刺下,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布绑嘹。 她就那樣靜靜地躺著,像睡著了一般橘茉。 火紅的嫁衣襯著肌膚如雪工腋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天畅卓,我揣著相機(jī)與錄音擅腰,去河邊找鬼。 笑死翁潘,一個胖子當(dāng)著我的面吹牛趁冈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拜马,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼渗勘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俩莽?” 一聲冷哼從身側(cè)響起旺坠,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扮超,沒想到半個月后取刃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹋肮,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年璧疗,在試婚紗的時候發(fā)現(xiàn)自己被綠了坯辩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡病毡,死狀恐怖濒翻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啦膜,我是刑警寧澤有送,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布堰汉,位于F島的核電站盟猖,受9級特大地震影響鼻吮,放射性物質(zhì)發(fā)生泄漏武福。R本人自食惡果不足惜重慢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一兔辅、第九天 我趴在偏房一處隱蔽的房頂上張望数初。 院中可真熱鬧鹤啡,春花似錦肌稻、人聲如沸清蚀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枷邪。三九已至,卻和暖如春诺凡,著一層夾襖步出監(jiān)牢的瞬間东揣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工腹泌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘶卧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓凉袱,卻偏偏與公主長得像芥吟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绑蔫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355