threadlocal 是執行緒私有領地,其他執行緒無法訪問。你知道嗎?據說這段**可能會造成記憶體洩漏,,,什麼,不知道?本文首先給出乙個簡單的使用示例,接下來主要解析threadlocal的原理,繼而作圖以生動地表示threadlocal的底層儲存關係,探索可能出現的記憶體洩漏,最後給出乙個threadlocal的正確使用姿勢。
無妨,寫這篇文章之前偶也不知道,一起來學習下吧。
public
static
void
main
(string[
] args)
,"t1").
start()
; system.out.
println
("main thread print tl: "
+ tl.
get())
;}
明確乙個問題
我們知道threadlocal用於儲存執行緒私有變數,那麼變數存在**呢?
答:
threadlocal.threadlocalmap threadlocals = null;
public
void
set(t value)
public t get()
}return
setinitialvalue()
;}
以上,set、get方法原始碼解析完畢,只有寥寥數行**,相當簡單。若還是似懂非懂,無妨,看我作圖:
該圖描述了threadlocal變數的儲存關係。分析一下這個圖:
為什麼r2是弱引用?
答:弱引用特性:只有弱引用指向的物件,每次gc都會被**。這樣子,當r1斷開後,因為唯一指向threadlocal物件的引用r2是弱引用,在下次gc時threadlocal物件就會被**,從而不會造成記憶體洩漏。
tips:因此每次使用完threadlocal,要記得顯示指定 tl = null;還存在記憶體洩漏嗎?
答:存在。
若threadlocal物件被**,那麼key就會變為null,那麼我們再也無法通過原來的key值獲得其對應的value。
因為r3是強引用,所以threadlocalmap會一直存在,進而value被threadlocalmap通過r4(強引用)所引用,也會一直存在。
value一直存在於記憶體,而再也不會被訪問到,這也是記憶體洩漏。
tips:每次用完threadlocal,顯示地刪除這個變數。tl.remove();經過以上學習,下面給出乙個筆者認為完善的示例,防止記憶體洩漏。
public
static
void
main
(string[
] args)
框架中的應用。spring採用threadlocal的方式,來保證單個執行緒中的資料庫操作使用的是同乙個資料庫連線。
實際工作中的應用。我們知道******dataformat不是執行緒安全的。所以如果宣告為全域性變數會有併發安全隱患。一般會在使用這個類的方法裡建立******dataformat物件,這樣不會有併發隱患。但是方法內部的物件在方法執行完其生命週期就結束了,如果乙個請求在呼叫鏈路的n個方法中都呼叫了******dataformat,是不是要建立n個物件?此時我們可以將其宣告為threadlocal,乙個執行緒在其生命週期內使用同乙個******dataformat,不同物件之間使用各自的******dataformat物件,形成執行緒間的資料隔離,不會有併發安全隱患。然而這種場景,適用於乙個執行緒有多個方法呼叫都用到了******dataformat,可以減少建立物件的次數。如果生命週期內只有乙個方法使用了這個物件,在方法裡建立就好了。
thread中還存在乙個屬性inheritablethreadlocals,可以繼承父執行緒中的inheritablethreadlocals 的值。
/*
* inheritablethreadlocal values pertaining to this thread. this map is
* maintained by the inheritablethreadlocal class.
*/threadlocal.threadlocalmap inheritablethreadlocals = null;
建立執行緒物件的時候,有如下一行**。若inheritthreadlocals 是true,且父執行緒的inheritablethreadlocals 不是null,則當前執行緒的inheritablethreadlocals 使用父執行緒中inheritablethreadlocals 的值。
if
(inheritthreadlocals && parent.inheritablethreadlocals != null)
this
.inheritablethreadlocals =
threadlocal.
createinheritedmap
(parent.inheritablethreadlocals)
;
ThreadLocal原始碼理解
threadlocal其實原理是建立了多份相同資料儲存在堆記憶體上,每個執行緒的thread類裡有threadlocal.threadlocalmap threadlocals的屬性來指向存位置,所以每個執行緒修改都不會影響到其他執行緒的資料 首先說下下面用到的東西 threadlocalmap為t...
ThreadLocal原始碼分析
在理解handler looper之前,先來說說threadlocal這個類,聽名字好像是乙個本地執行緒的意思,實際上它並不是乙個thread,而是提供乙個與執行緒有關的區域性變數功能,每個執行緒之間的資料互不影響。我們知道使用handler的時候,每個執行緒都需要有乙個looper物件,那麼and...
ThreadLocal 原始碼解讀
在正式讀 前先簡單介紹threadlocal的實現方式。每個執行緒都會有乙個threadlocalmap,只有在使用到threadlocal的時候才會初始化threadlocalmap。需要儲存的物件t會被放到entry裡面儲存在threadlocalmap的陣列中,entry是乙個鍵值對的資料結構...