設(shè)計模式—單例

只介紹懶漢模式,并且線程安全的寫法

Java版本

1努潘、雙重檢查坤学,加鎖

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;
    }
}

分析:當(dāng)同時有兩個線程訪問getInstance()時深浮,synchronized 前的instance == null兩個線程都會通過,當(dāng)執(zhí)行synchronized (Singleton.class)時候會有一個線程進(jìn)入菌瘫,另一個線程等待的情況布卡,進(jìn)入的線程會再次對instance == null進(jìn)行判斷并創(chuàng)建一個Singleton的實例,然后結(jié)束synchronized 代碼塊栖忠。另一個等待線程進(jìn)入synchronized 代碼塊贸街,在進(jìn)行instance == null判斷時會發(fā)現(xiàn)instance 已經(jīng)不再為null,從而不再創(chuàng)建Singleton的實例捐川,這樣就可以確保Singleton對象在多線程情況下也只有一個實例逸尖。那你會不會問在synchronized 前的instance == null又有什么作用呢?這個主要是考慮效率的問題冷溶,如果不在synchronized 前加上instance == null逞频,就會發(fā)現(xiàn)每次調(diào)用都會對線程加鎖,消耗資源又達(dá)不到高效性苗胀。

2瓦堵、靜態(tài)內(nèi)部類菇用,寫法簡單優(yōu)雅

public class Singleton {
    // --- 靜態(tài)內(nèi)部類 線程安全
    private Singleton() {}

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

    private static class Holder {
        private static Singleton instance = new Singleton();
    }

}

分析:其實這是一種偷懶的線程安全實現(xiàn)方法陷揪,為什么說是偷懶那?那是因為這種實現(xiàn)利用了類的加載是線程安全的原理卦绣。當(dāng)這個Singleton 被加載的時候飞蚓,其中的內(nèi)部類Holder 并不會被加載,只有當(dāng)調(diào)用getInstance()中的Holder.instance時Holder 才會被加載溅漾,而類的加載一定是線程安全著榴,至于為什么類的加載是線程安全的請 自行百度

Kotlin版本

1、雙重檢查缝龄,加鎖

class Singleton private constructor() : IImageLoader {
    companion object {
        @Volatile
        private var INSTANCE: Singleton ? = null

        fun instance(): Singleton {
            INSTANCE ?: synchronized(Singleton @ this) {
                if (INSTANCE == null)
                    INSTANCE = Singleton (loader)
            }
            return INSTANCE!!
        }
    }
}

或者

class SingletonK private constructor() {
    companion object {
        val Instanc: SingletonK by lazy { SingletonK() }
    }
}

分析:為什么val Instanc: SingletonK by lazy { SingletonK() }這樣就可以實現(xiàn)線程安全叔壤?這要看lazy的實現(xiàn)源碼lazy其實是可以有參數(shù)的口叙,它的參數(shù)類型是LazyThreadSafetyMode,當(dāng)我們不傳的時候默認(rèn)是LazyThreadSafetyMode.SYNCHRONIZED也就是線程安全,那么我們再看看這種情況下的具體實現(xiàn)俺亮!

@kotlin.jvm.JvmVersion
public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
        when (mode) {
            LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
            LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
            LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
        }
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
    private var initializer: (() -> T)? = initializer
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE
    // final field is required to enable safe publication of constructed instance
    private val lock = lock ?: this

    override val value: T
        get() {
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST")
                return _v1 as T
            }

            return synchronized(lock) {
                val _v2 = _value
                if (_v2 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST") (_v2 as T)
                }
                else {
                    val typedValue = initializer!!()
                    _value = typedValue
                    initializer = null
                    typedValue
                }
            }
        }

    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE

    override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."

    private fun writeReplace(): Any = InitializedLazyImpl(value)
}

當(dāng)我們看到get中的下面代碼

    val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
        @Suppress("UNCHECKED_CAST")
        return _v1 as T
    }

    return synchronized(lock) {
        val _v2 = _value
        if (_v2 !== UNINITIALIZED_VALUE) {
            @Suppress("UNCHECKED_CAST") (_v2 as T)
        }
        else {
            val typedValue = initializer!!()
            _value = typedValue
            initializer = null
            typedValue
        }
    }

這就不用我多說了,底層實現(xiàn)還是一個雙重檢查加鎖的實現(xiàn)F艟摺!拷沸!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撞芍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子序无,更是在濱河造成了極大的恐慌,老刑警劉巖米罚,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拔莱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)讼渊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門爪幻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來须误,“玉大人,你說我怎么就攤上這事京痢〖酪” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵钉赁,是天一觀的道長携茂。 經(jīng)常有香客問我,道長姓蜂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任逮京,我火速辦了婚禮束莫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘策严。我一直安慰自己饿敲,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布倔韭。 她就那樣靜靜地躺著瓢对,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硕蛹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機(jī)與錄音埃仪,去河邊找鬼。 笑死琉兜,一個胖子當(dāng)著我的面吹牛毙玻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桑滩,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼幌氮!你這毒婦竟也來了缭受?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤该互,失蹤者是張志新(化名)和其女友劉穎米者,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宇智,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡蔓搞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了随橘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喂分。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖机蔗,靈堂內(nèi)的尸體忽然破棺而出蒲祈,到底是詐尸還是另有隱情,我是刑警寧澤梆掸,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站酿愧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏邀泉。R本人自食惡果不足惜嬉挡,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望汇恤。 院中可真熱鬧庞钢,春花似錦、人聲如沸因谎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽财岔。三九已至风皿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匠璧,已是汗流浹背桐款。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留夷恍,地道東北人魔眨。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遏暴。 傳聞我的和親對象是個殘疾皇子侄刽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355