<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    深入淺出ThreadLocal

    一、ThreadLocal概述

           學習JDK中的類,首先看下JDK API對此類的描述,描述如下:

    JDK API 寫道
    該類提供了線程局部 (thread-local) 變量。這些變量不同于它們的普通對應物,因為訪問某個變量(通過其 get 或 set 方法)的每個線程都有自己的局部變量,它獨立于變量的初始化副本。ThreadLocal 實例通常是類中的 private static 字段,它們希望將狀態與某一個線程(例如,用戶 ID 或事務 ID)相關聯。 

        API表達了下面幾種觀點:

    1、ThreadLocal不是線程,是線程的一個變量,你可以先簡單理解為線程類的屬性變量。

    2、ThreadLocal 在類中通常定義為靜態類變量。

    3、每個線程有自己的一個ThreadLocal,它是變量的一個‘拷貝’,修改它不影響其他線程。


        既然定義為類變量,為何為每個線程維護一個副本(姑且成為‘拷貝’容易理解),讓每個線程獨立訪問?多線程編程的經驗告訴我們,對于線程共享資源(你可以理解為屬性),資源是否被所有線程共享,也就是說這個資源被一個線程修改是否影響另一個線程的運行,如果影響我們需要使用synchronized同步,讓線程順序訪問。


       ThreadLocal適用于資源共享但不需要維護狀態的情況,也就是一個線程對資源的修改,不影響另一個線程的運行;這種設計是‘空間換時間’,synchronized順序執行是‘時間換取空間’


    二、ThreadLocal方法介紹



     T get() 
              返回此線程局部變量的當前線程副本中的值。
    protected  T initialValue() 
              返回此線程局部變量的當前線程的“初始值”。
     void remove() 
              移除此線程局部變量當前線程的值。
     void set(T value) 
              將此線程局部變量的當前線程副本中的值設置為指定值。


    三、深入源碼

        ThreadLocal有一個ThreadLocalMap靜態內部類,你可以簡單理解為一個MAP,這個‘Map’為每個線程復制一個變量的‘拷貝’存儲其中。

        當線程調用ThreadLocal.get()方法獲取變量時,首先獲取當前線程引用,以此為key去獲取響應的ThreadLocalMap,如果此‘Map’不存在則初始化一個,否則返回其中的變量,代碼如下:


     public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
    ThreadLocalMap.Entry e = map.getEntry(this);
    if (e != null)
    return (T)e.value;
    }
    return setInitialValue();
    }

        調用get方法如果此Map不存在首先初始化,創建此map,將線程為key,初始化的vlaue存入其中,注意此處的initialValue,我們可以覆蓋此方法,在首次調用時初始化一個適當的值。setInitialValue代碼如下:

        private T setInitialValue() {
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
    map.set(this, value);
    else
    createMap(t, value);
    return value;
    }


        set方法相對比較簡單如果理解以上倆個方法,獲取當前線程的引用,從map中獲取該線程對應的map,如果map存在更新緩存值,否則創建并存儲,代碼如下:

        public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
    map.set(this, value);
    else
    createMap(t, value);
    }


        對于ThreadLocal在何處存儲變量副本,我們看getMap方法:獲取的是當前線程的ThreadLocal類型的threadLocals屬性。顯然變量副本存儲在每一個線程中。


    /**
    * 獲取線程的ThreadLocalMap 屬性實例
    */
    ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
    }


        上面我們知道變量副本存放于何處,這里我們簡單說下如何被java的垃圾收集機制收集,當我們不在使用是調用set(null),此時不在將引用指向該‘map’,而線程退出時會執行資源回收操作,將申請的資源進行回收,其實就是將屬性的引用設置為null。這時已經不在有任何引用指向該map,故而會被垃圾收集。


     四、ThreadLocal應用示例


          在我的另一篇文章,對ThreadLocal的使用做了一個實例,此示例也可以用作生產環境,請參見:http://ari.iteye.com/blog/757641



    如有問題請留言討論,謝謝

    posted on 2011-05-10 21:02 空白 閱讀(402) 評論(0)  編輯  收藏 所屬分類: Java

    <2011年5月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    導航

    統計

    常用鏈接

    留言簿(1)

    隨筆分類(15)

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产在线a免费观看| 99re在线精品视频免费| 亚洲三级中文字幕| 四虎国产成人永久精品免费| 国产午夜亚洲精品理论片不卡| 亚洲美女精品视频| 69视频在线是免费观看| 亚洲精品国产V片在线观看| 美女免费精品高清毛片在线视| 国产乱子伦精品免费无码专区| 边摸边吃奶边做爽免费视频99| 亚洲精品无码av天堂| 国产黄色免费观看| 亚洲大尺度无码专区尤物| 亚洲AV无码资源在线观看| 免费看搞黄视频网站| 国产精品成人无码免费| 青青免费在线视频| 亚洲国产精品一区第二页| 2021在线永久免费视频| 亚洲乱妇熟女爽到高潮的片| 亚洲国产成人五月综合网 | 日韩a毛片免费观看| 国产福利在线观看免费第一福利| 亚洲色无码一区二区三区| 久久亚洲欧美国产精品| 日产国产精品亚洲系列| 在线观看片免费人成视频无码| 亚洲精品第五页中文字幕| 成年女人色毛片免费看| 波霸在线精品视频免费观看| 久久精品国产亚洲av水果派| 免费一级毛片在线播放视频| 亚洲中文字幕久在线| 亚洲av无码天堂一区二区三区| 无码国产精品一区二区免费16| 亚洲欧洲日产国码二区首页| 91精品手机国产免费| 亚洲av日韩av永久在线观看| 亚洲国产精品一区二区成人片国内 | 免费A级毛片无码无遮挡内射|