Java 單例模式 Singleton Pattern

餓漢式 線程安全

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

    private Singleton() {
        System.out.println("Constructing Singleton");
    }

    public static Singleton getInstance() {
        return instance;
    }
}
  • instance 聲明為 私有靜態(tài) 變量缕减, 在類(lèi)加載時(shí)即調(diào)用構(gòu)造函數(shù)惫皱,因此線程安全
  • 缺點(diǎn):不管是否調(diào)用 getInstance 使用實(shí)例叙量,都會(huì)占用內(nèi)存空間

Double Checked Locking 線程安全

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        System.out.println("Constructing Singleton");
    }

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

        return instance;
    }
}

注意事項(xiàng):

  • instance 聲明為 私有靜態(tài) 變量
  • 構(gòu)造函數(shù)聲明為 私有
  • getInstace 函數(shù)聲明為 公有靜態(tài) 方法
  • 可能存在指令重排的問(wèn)題。
    • 解決:用 volatile 修飾 instance private static volatile Singleton instance;
    • volatile修飾的話就可以確保 instance = new Singleton(); 對(duì)應(yīng)的指令不會(huì)重排序

占位符模式 線程安全

public class Singleton {
    // 成員內(nèi)部類(lèi)
    private static class SingletonHolder {
        static Singleton instance = new Singleton();
    }

    private Singleton() {
        System.out.println("Constructing Singleton");
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}
  • 內(nèi)部類(lèi) SingletonHolder 只有在 getInstance() 方法第一次調(diào)用的時(shí)候才會(huì)被加載(實(shí)現(xiàn)了lazy隘庄,避免了餓漢模式的缺點(diǎn))
  • static 域中修改共享變量是線程安全的,由JVM保障

通過(guò)反射機(jī)制攻擊單例模式

public static void main(String[] args) throws Exception {
    Constructor c = Singleton.class.getDeclaredConstructor(null);
    c.setAccessible(true);

    Singleton s1 = (Singleton)c.newInstance();
    Singleton s2 = (Singleton)c.newInstance();
}

以上的代碼可以多次調(diào)用構(gòu)造函數(shù)癣亚,生成多個(gè)對(duì)象實(shí)例丑掺。

可以通過(guò)修改構(gòu)造函數(shù)抵御這種攻擊:

private static boolean flag = true;
// 私有構(gòu)造函數(shù)
private Singleton() {
    synchronized (Singleton.class) {
        if(flag) {
            flag = !flag;
            System.out.println("Constructing Singleton");
        } else {
            throw new RuntimeException("Reject Constructing Singleton");
        }
    }
}

引用:
如何防止單例模式被JAVA反射攻擊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市述雾,隨后出現(xiàn)的幾起案子街州,更是在濱河造成了極大的恐慌,老刑警劉巖玻孟,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唆缴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡黍翎,警方通過(guò)查閱死者的電腦和手機(jī)面徽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人趟紊,你說(shuō)我怎么就攤上這事氮双。” “怎么了霎匈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵戴差,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我铛嘱,道長(zhǎng)暖释,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任墨吓,我火速辦了婚禮球匕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肛真。我一直安慰自己谐丢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蚓让。 她就那樣靜靜地躺著乾忱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪历极。 梳的紋絲不亂的頭發(fā)上窄瘟,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音趟卸,去河邊找鬼蹄葱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锄列,可吹牛的內(nèi)容都是我干的图云。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼邻邮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼竣况!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起筒严,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丹泉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后鸭蛙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體摹恨,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年娶视,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晒哄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖揩晴,靈堂內(nèi)的尸體忽然破棺而出勋陪,到底是詐尸還是另有隱情,我是刑警寧澤硫兰,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布诅愚,位于F島的核電站,受9級(jí)特大地震影響劫映,放射性物質(zhì)發(fā)生泄漏违孝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一泳赋、第九天 我趴在偏房一處隱蔽的房頂上張望雌桑。 院中可真熱鬧,春花似錦祖今、人聲如沸校坑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耍目。三九已至,卻和暖如春徐绑,著一層夾襖步出監(jiān)牢的瞬間邪驮,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工傲茄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毅访,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓盘榨,卻偏偏與公主長(zhǎng)得像喻粹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子草巡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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