正確解讀ThreadLocal

在Android的消息機制中,Handler是非常重要的一部分,而完全要理解Handler的機制,首先應(yīng)該理解ThreadLocal,關(guān)于ThreadLocal,見到很多地方叫做線程本地變量,也有些地方叫做線程本地存儲,其實意思差不多。可能很多人都知道ThreadLocal為變量在每個線程中都創(chuàng)建了一個副本,那么每個線程可以訪問自己內(nèi)部的副本變量,這樣的詞容易讓人產(chǎn)生誤解或者迷惑。
首先,從最新的ThreadLocal源碼看,ThreadLocal并未創(chuàng)建任何本地變量,也沒有copy副本的存在,是直接用的Thread對象的成員變量,因此叫做"線程變量幫助類"其實更合適,它的作用就是拿到當前線程對象的Object[] value數(shù)組,然后進行存儲和取值,因為這屬于每個線程的內(nèi)部變量數(shù)組,因此也不存在共享,所以也就沒有線程安全的問題。
先看一個例子:

ThreadLocal例子.png

例子可以看出不同的線程得到的值是不同的,說明ThreadLocal可以使同一個變量在不同的線程里有不同的值,為什么同一個變量在不同的線程的會表現(xiàn)出不同的值呢,源碼說明一切:

先看set方法:

set(T value).png
得到當前Thread對象的Values值.png

可以看出ThreadLocal的Values引用直接指向Thread的localValues值??聪聀ut()方法的實現(xiàn)。

put.png

很好理解,可以簡單看做用單個數(shù)組來實現(xiàn)的簡易hashmap的,hashmap的key是當前ThreadLocal對象的hash值與當前數(shù)組長度的求模運算,存入在數(shù)組的index位置,value就是當前的存入值,這個值總是放在index+1的位置,可以理解為index和index+1這兩個位置就是hashmap的Entry。好像在jdk1.7之前就是用hashmap來實現(xiàn)的,原理都是一樣的。這樣是Thread類更加的輕量化。

get()

通過上面的分析get函數(shù)也很好理解了。先得到當前線程對象的Values對象,然后得到Values中的Object[] table數(shù)組,從數(shù)組中取出值。

ThreadLocal 實例通常建議是用 private static 字段,至于原因想不太清楚。但這不是絕對的,在Android的事件機制Looper中

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

這就不是一個private變量,至于靜態(tài)

public static @Nullable Looper myLooper() {    
    return sThreadLocal.get();
}

因為需要靜態(tài)方法獲取Looper對象,所以就必須是靜態(tài)的的吧??吹揭环N說法是設(shè)置static 是因為ThreadLocal支持線程范圍生命周期的變量,所以不屬于類的屬性。不知是否有些牽強。
關(guān)于內(nèi)存泄露的問題

/** Weak reference to this thread local instance. */
private final Reference<ThreadLocal<T>> reference = new WeakReference<ThreadLocal<T>>(this);

因為是軟引用持有,所以不會存在內(nèi)存泄露的問題。但確定不需要使用的時候最好調(diào)用remove()方法來釋放內(nèi)存。

簡單總結(jié)

判斷是否需要對資源進行同步的判斷準則是,當前獲取(get)資源是否會有其他線程進行修改(set)或者當前進行修改的資源是否會有其他線程可以獲取。

  • synchronized——串行訪問
  • volatile——主內(nèi)存刷新,不存在線程副本
  • ThreadLocal——線程空間內(nèi)的全局變量
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,887評論 11 349
  • Android Handler機制系列文章整體內(nèi)容如下: Android Handler機制1之ThreadAnd...
    隔壁老李頭閱讀 7,856評論 4 30
  • Java SE 基礎(chǔ): 封裝、繼承、多態(tài) 封裝: 概念:就是把對象的屬性和操作(或服務(wù))結(jié)合為一個獨立的整體,并盡...
    Jayden_Cao閱讀 2,259評論 0 8
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,917評論 0 11
  • 昨天天西安下雪了,美呆了[色](圖來自早上群內(nèi)一朋友曬的雪景圖) 有一起相約北方看雪的嗎? 我在廣州的寒潮里,蹜蹜...
    艾哥閱讀 286評論 0 1

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