單例

項目中需要有一些工具類提供服務(wù),例如線程池陆馁,http調(diào)用工具等岖免,有兩種設(shè)計:單例和靜態(tài)方法方式岳颇。
單例方式:如果這個類需要維持一些狀態(tài),比較適合使用單例模式存在颅湘。單例模式還可以延遲加載赦役,而且單例更加面向?qū)ο螅梢岳^承基類實現(xiàn)接口等方式提供不同功能的實現(xiàn)栅炒。

靜態(tài)方法:如果一些不需要維護(hù)狀態(tài)的類可以設(shè)計成靜態(tài)方法掂摔,訪問效率會好一些。例如java中的Math類赢赊。


單例大概有幾種實現(xiàn)方式乙漓,餓漢式、懶漢式释移、雙重檢驗鎖叭披、靜態(tài)內(nèi)部類等。
餓漢式線程安全玩讳,類加載時即加載涩蜘,不支持延時加載,而懶漢式延遲加載熏纯,但不是線程安全的同诫。

1、雙重檢驗鎖單例:

public class SingleTon {

    private volatile static SingleTon singleTon = null;

    private SingleTon(){}

    public static SingleTon getSingleTon() {
        if (singleTon == null) {
            synchronized (SingleTon.class) {
                if (singleTon == null) {
                    singleTon = new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

第一個null判斷是為了減少進(jìn)入synchronized塊解決效率問題樟澜。
第二個null判斷是為了攔截:線程a進(jìn)入synchronized塊后實例化釋放鎖后误窖,線程b從阻塞中醒來再次進(jìn)入synchronized塊執(zhí)行加載。

jvm有指令重排秩贰,所以需要使用volatile關(guān)鍵字防止指令重排霹俺。
singleTon = new SingleTon();不是線程安全的操作,包含了3個步驟毒费。
1.在堆內(nèi)為SingleTon開辟空間丙唧。
2.在堆實例化SingleTon對象,加載各個參數(shù)觅玻。
3.將singleTon引用指向這塊內(nèi)存想际。
如果不使用volatile關(guān)鍵字培漏,jvm可能發(fā)生這樣的執(zhí)行序列:1-3-2,在沒有實例化完成時就將引用指向了這塊內(nèi)存沼琉,導(dǎo)致代碼判斷null為非空,將對象返回使用桩匪,造成問題打瘪。


2、靜態(tài)內(nèi)部類單例

public class AsyncExecutorUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncExecutorUtils.class);

    private AsyncExecutorUtils() {
        LOGGER.info("AsyncExecutorUtils lazy init by jvm...");
    }

    private static class ExecutorHolder {
        static AsyncExecutorUtils INSTANCE = new AsyncExecutorUtils();
    }

    public static AsyncExecutorUtils getInstance() {
        return ExecutorHolder.INSTANCE;
    }

這是我的一段代碼傻昙,線程池采用了單例模式闺骚。將獲取實例的靜態(tài)方法改成從靜態(tài)內(nèi)部類ExecutorHolder里面的靜態(tài)成員變量INSTANCE里面獲取。

靜態(tài)內(nèi)部類方式如何實現(xiàn)延遲加載:
因為我們將實例放在了內(nèi)部類里面妆档,所以要保證內(nèi)部類是延遲加載的僻爽,java中的類分為主動引用被動引用的區(qū)別,只有主動引用的時候才會初始化該類贾惦。主動引用有且只有5中情況:
1.new胸梆、getstatic、putstatic或invokestatic這四條字節(jié)碼指令须板,對應(yīng)常用的操作是使用new關(guān)鍵字實例化對象碰镜、獲取或者設(shè)置靜態(tài)變量,調(diào)用靜態(tài)方法习瑰。(newarray指令觸發(fā)的只是數(shù)組類型本身的初始化绪颖,而不會導(dǎo)致其相關(guān)類型的初始化)
2.反射調(diào)用。
3.如果是某一個類的父類甜奄,這個子類初始化會觸發(fā)父類初始化柠横。
4.main方法所在類
5.當(dāng)使用JDK 1.7等動態(tài)語言支持時,如果一個java.lang.invoke.MethodHandle實例最后的解析結(jié)果REF_getStatic课兄、REF_putStatic牍氛、REF_invokeStatic的方法句柄,并且這個方法句柄所對應(yīng)的類沒有進(jìn)行過初始化烟阐,則需要先觸發(fā)其初始化糜俗。

其他方式均為被動引用,不會被初始化曲饱。所以這個靜態(tài)內(nèi)部類ExecutorHolder只有在程序中第一次使用時調(diào)用到他的靜態(tài)獲取方法getInstance()時才會初始化悠抹,實現(xiàn)延時加載。

靜態(tài)內(nèi)部類方式如何保證線程安全:
可以看到getInstance()只返回同一個static的INSTANCE扩淀,而類的初始化是由jvm初始化楔敌,jvm肯定會保證類的初始化的線程安全性。具體實現(xiàn)大致是保證只有一個線程獲得鎖執(zhí)行初始化驻谆,其他阻塞線程恢復(fù)過來不會再去執(zhí)行初始化卵凑。


感覺上靜態(tài)內(nèi)部類實現(xiàn)更加優(yōu)雅簡潔庆聘,但是這種方式不能傳參數(shù),但是大多數(shù)這種單例類都不需要傳參勺卢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伙判,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子黑忱,更是在濱河造成了極大的恐慌宴抚,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甫煞,死亡現(xiàn)場離奇詭異菇曲,居然都是意外死亡,警方通過查閱死者的電腦和手機抚吠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門常潮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人楷力,你說我怎么就攤上這事喊式。” “怎么了萧朝?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵垃帅,是天一觀的道長。 經(jīng)常有香客問我剪勿,道長贸诚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任厕吉,我火速辦了婚禮酱固,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘头朱。我一直安慰自己运悲,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布项钮。 她就那樣靜靜地躺著班眯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烁巫。 梳的紋絲不亂的頭發(fā)上署隘,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機與錄音亚隙,去河邊找鬼磁餐。 笑死,一個胖子當(dāng)著我的面吹牛阿弃,可吹牛的內(nèi)容都是我干的诊霹。 我是一名探鬼主播羞延,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脾还!你這毒婦竟也來了伴箩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鄙漏,失蹤者是張志新(化名)和其女友劉穎嗤谚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泥张,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡呵恢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年鞠值,在試婚紗的時候發(fā)現(xiàn)自己被綠了媚创。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡彤恶,死狀恐怖钞钙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情声离,我是刑警寧澤芒炼,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站术徊,受9級特大地震影響本刽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赠涮,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一子寓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笋除,春花似錦斜友、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铅檩。三九已至聚唐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間骤肛,已是汗流浹背酱吝。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工虹菲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掉瞳。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓毕源,卻偏偏與公主長得像浪漠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子霎褐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

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