threadlocal可以設定儲存屬於當前執行緒的物件,存在當前執行緒(currentthread)的threadlocals中,threadlocals是threadlocalmap類的物件。
threadlocal的作用:
儲存單個執行緒上下文資訊。比如儲存id等;減少引數傳遞。比如做乙個trace工具,能夠輸出工程從開始到結束的整個一次處理過程中所有的資訊,從而方便debug。由於需要在工程各處隨時取用,可放入threadlocal。
原理
public
void
set(t value)
public t get()
}return
setinitialvalue()
;//如果map中沒有或map為空,則返回初始值,注意初始值可能為null,也可能為之前設定的初始值。要想設定初始值,得使用子類suppliedthreadlocal,也就是呼叫threadlocal.withinitial()建立物件。
}
public
static
threadlocal
withinitial
(supplier<
?extends
s> supplier)
static
final
class
suppliedthreadlocal
extends
threadlocal
@override
protected t initialvalue()
}private
static threadlocal
int_of_thread = threadlocal.
withinitial((
)->
"kyrie");
//像上述這樣構造threadlocal物件,將返回子類suppliedthreadlocal的物件,使用到了threadlocal裡面的靜態內部類suppliedthreadlocal。
記憶體洩漏問題static
class
threadlocalmap
}
[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-ccrrlznp-1586486230724)(c:\users\kyrie\pictures\threadlocal.png)]
上圖是threadlocal物件及引用,threadlocalmap物件及引用的分布。
map中key使用弱引用的原因
如果使用強引用,當threadlocal物件(假設為threadlocal@123456)的引用(即:tl_int,是乙個強引用,指向threadlocal@123456)被**了,threadlocalmap本身依然還持有threadlocal@123456的強引用,如果沒有手動刪除這個key,則threadlocal@123456不會被**,所以只要當前執行緒不消亡,threadlocalmap引用的那些物件就不會被**,可以認為這導致entry記憶體洩漏。
如果使用弱引用,那指向threadlocal@123456物件的引用就兩個:tl_int強引用,和threadlocalmap中entry的弱引用。一旦tl_int被**,則指向threadlocal@123456的就只有弱引用了,在下次gc的時候,這個threadlocal@123456就會被**。
key被刪了之後,變成了null,value更是無法被訪問到了!針對這一問題,threadlocalmap類的設計本身已經有了這一問題的解決方案,那就是在每次get()/set()/remove()threadlocalmap中的值的時候,會自動清理key為null的value。如此一來,value也能被**了。
如果面試問為什麼不將value也設定為弱引用,方便清除處理?
那是因為在map外部很有可能沒有value的強引用,value就可能隨時被gc,那就沒有使用threadlocal的必要了。(key在map外部一般會有乙個全域性的強引用,和value的情況不一樣)
參考文章
ThreadLocal 及其機制
一 threadlocal類的例子 某一線程中的區域性變數會被其他執行緒所改寫,所以有了threadlocal類,可以用這個類來儲存區域性變數,以保證區域性變數的安全!以下兩個例子其中之一使用了threadlocal類,另乙個未用,注意觀察其結果的不同 class unsafetask implem...
ThreadLocal使用介紹
首先有幾點需要大家清楚的 1 threadlocal 只是對需要儲存的物件的管理,而儲存實際是由當前thread 負責。個人理解為threadlocal 是乙個操作thread.threadlocals 的工具。2 使用threadlocal 可以使物件達到執行緒隔離的目的。同乙個threadloc...
ThreadLocal使用場景及其優勢
曾經很疑惑threadlocal是幹什麼用?什麼場景下要用?查了幾篇文章,都說它的優勢是執行緒安全,想必他的作用就是為了執行緒安全吧。仔細理解後發現,原來我們常用的區域性變數和靜態變數,在某種情況下無法滿足要求,比如,我要求快取乙個變數,這個時候你肯定會說搞乙個靜態map存一下就ok了,但是有幾個問...