問二十七:ThreadLocal源碼解析

ThreadLocal概述:

ThreadLocal是一個本地線程副本變量工具類,運用到了線程封閉技術

用來維護線程中的變量不被其他線程干擾而出現的一個結構,內部包含一個ThreadLocalMap類(該類由一個繼承自虛引用的Entry來存具體的值,需要留意還有一個用來存Entry的table數組),該類爲Thread類的一個實例屬性(非static的成員變量),該Entry存儲的key爲ThreadLocal對象自身,value爲我們要存儲的值或對象。

這樣一來,在不同線程中,持有的其實都是當前線程的變量副本,與其他線程完全隔離,以此來保證線程執行過程中不受其他線程的影響。

 

ThreadLocal使用流程:

使用時可以重寫initialValue()方法,當線程進行get調用時,獲取當前線程對象實例的threadLocals這個成員變量。

它的類型爲ThreadLocal.ThreadLocalMap,內部是一個繼承了WeakReference<ThreadLocal<?>>的Entry,可以存當前ThreadLocal引用和對應的值。

獲取之後進行一個是否爲null的判斷,Thread類中默認爲null,寫入或者更新通過initialValue()確定的值。

當線程需要取出線程本地變量的時候,還是從Thread實例對象中取出之前賦好值的threadLocals,再從ThreadLocalMap.Entry中取出實際對應的值。

因此ThreadLocal實際上是不存值的,只是起到存入或取出線程實例中ThreadLocalMap中線程對應值的功能。

只要線程處於活躍狀態(alive)並且ThreadLocal實例可以訪問,那麼每個線程都會持有着一個線程本地變量副本的隱式副本。

線程消失之後,線程本地實例的所有相關副本都會進行垃圾回收(除非存在對這些副本的其他引用)

注:因此雖然ThreadLocal它的底層存儲結構(ThreadLocalMap)是弱引用(Entry extends WeakReference<java.ThreadLocal<?>>),但是並不是這個弱引用的值一被置爲null就會被回收,因爲存活着的那個線程對它還有一個強引用  (ThreadLocal.ThreadLocalMap threadLocals = Entry(ThreadLocal<?> k, null);)

源代碼解析:ThreadLocal

 

內存泄露問題:

會引發內存泄露↓

 


通過調用remove()方法避免內存溢出

 

實際運用場景:

如果用SimpleDateFormat對象轉換日期格式,但是不想每次請求創建新的SimpleDateForma對象,爲了可以解決併發場景下的性能問題可以使用到ThreadLocal

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章