如何優(yōu)雅的實(shí)現(xiàn)ThreadLocal

大部分翻譯自How is ThreadLocal implemented?對(duì)代碼作了更新
這是一個(gè)關(guān)于跳脫固有框架思考的例子,建議你花5分鐘閱讀全文,一定有所收獲

ThreadLocal介紹

Implements a thread-local storage, that is, a variable for which each thread has its own value. All threads share the same {@code ThreadLocal} object ,but each sees a different value when accessing it, and changes made by one thread do not affect the other threads. The implementation supports {@code null} values.

大概意思是說,一個(gè)ThreadLocal變量可以為不同的線程保存不同的值

實(shí)現(xiàn)

通過介紹可知,可以為線程保存本地變量,那么我們可能需要一個(gè)Map對(duì)象,即ThreadLocal<T>變量內(nèi)部維護(hù)一個(gè)HashMap<Thread,T>對(duì)象,其中,KEY可以通過Thread.currentThread()來獲取,但是HashMap不是線程安全的,我們可以用Hashtable(相當(dāng)于為每個(gè)方法加了同步原語synchronize的HashMap,效率低)或者ConcurrentHashMap(鎖分段技術(shù),效率高點(diǎn))代替,一旦你使用這樣的方式實(shí)現(xiàn),那么需要面對(duì)的問題有兩:

  • 1、內(nèi)存泄漏風(fēng)險(xiǎn),因?yàn)镵EY為Thread
  • 2、同步的開銷

為了解決第一個(gè)問題可以考慮使用弱應(yīng)用替代Thread的強(qiáng)引用,但關(guān)于同步的開銷明顯是沒有更好的方法解決了?

但實(shí)際上JDK中的實(shí)現(xiàn)并不是這樣的且更加優(yōu)雅,前面我們考慮以Thread作為KEY記錄在ThreadLocal來為Thread保存線程獨(dú)有的變量,而JDK的實(shí)現(xiàn)則是剛好與我們相反,用Thread來記錄這樣的一個(gè)以ThreadLocal-Object的映射關(guān)系(不一定是用JAVA中的Map容器來實(shí)現(xiàn))

以Android23的為例子

public class Thread implements Runnable {
    ThreadLocal.Values localValues;
    // cut for brevity
}
public class ThreadLocal<T> {
    // cut for brevity
    static class Value {        
        private Object[] table;

        void put(ThreadLocal<?> keys, Object value) {
            cleanUp();
            int firstTombstone = -1;
            for (int index = key.hash & mask;; index = next(index)) {
                Object k = table[index];

                if (k == key.reference) {
                    // Replace existing entry.
                    table[index + 1] = value;
                    return;
                }
              }
            }//end put

            //........

        }//end Value

    public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }

    Values initializeValues(Thread current) {
        return current.localValues = new Values();
    }

    // ...
}//end ThreadLocal

Thread記錄了一個(gè)ThreadLocal.Value實(shí)例,用來記錄了[ThreadLocal實(shí)例-線程本地變量]的映射,Key為hash值,不用擔(dān)心內(nèi)存泄漏問題,并且避免了同步所帶來的開銷問題,的確是十分優(yōu)雅的實(shí)現(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,872評(píng)論 11 349
  • 前言 ThreadLocal很多同學(xué)都搞不懂是什么東西,可以用來干嘛。但面試時(shí)卻又經(jīng)常問到,所以這次我和大家一起學(xué)...
    liangzzz閱讀 12,660評(píng)論 14 228
  • Java SE 基礎(chǔ): 封裝、繼承、多態(tài) 封裝: 概念:就是把對(duì)象的屬性和操作(或服務(wù))結(jié)合為一個(gè)獨(dú)立的整體,并盡...
    Jayden_Cao閱讀 2,259評(píng)論 0 8
  • Android Handler機(jī)制系列文章整體內(nèi)容如下: Android Handler機(jī)制1之ThreadAnd...
    隔壁老李頭閱讀 7,851評(píng)論 4 30
  • 管理界有句很經(jīng)典的話:走多遠(yuǎn),都別忘了當(dāng)初為什么出發(fā)。于愛情婚姻而言,同樣適用。 今天是高晴和蘇曉結(jié)婚的5293天...
    九月雛菊閱讀 6,940評(píng)論 0 11

友情鏈接更多精彩內(nèi)容