【Java并發學習五】圖解ThreadLocal

簡單整理下ThreadLocal的原理,以及它需要注意的內存泄漏。

ThreadLocal原理

ThreadLocal不多介紹,可看作線程內的局部變量(這個比喻很貼切)。我們平時聲明的局部變量的范圍一般是方法內的,而ThreadLocal變量的范圍是整個線程。

我們先來看一段代碼demo:

public class Test {
    //可看作線程內聲明的局部變量
    static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public void a(){
        //設置線程內局部變量值為1
        threadLocal.set("1");
    }

    public void b(){
        //獲取線程內局部變量值
        System.out.println(threadLocal.get()); //輸出:1
        //設置線程內局部變量值為2
        threadLocal.set("2");
        //獲取線程內局部變量值
        System.out.println(threadLocal.get()); ////輸出:2
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.a();
        test.b();
    }

}

通過方法a()設置了線程局部變量ThreadLocal的值,然后再另一個方法b()中獲取并修改了它。由于調用時方法a()b()都在同一線程中,所以可以成功獲取和修改threadLocal

問題:那ThreadLocal是如何做到,使變量的值的使用范圍是整個線程的呢?

這主要得益于線程Thread類中的一個成員變量:ThreadLocalMap。這個Map的鍵值對是<ThreadLocal,Object>key是ThreadLocal對象,value是該ThreadLocal對象設置的值。

public class Thread implements Runnable {
  /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

ThreadLocalMap可看作保存著該線程內所有的 “線程局部變量”的集合。每個線程都維護著自己的線程局部變量集合:ThreadLocalMap

當我們設置一個ThreadLocal的值myThreadLocal.set("1")時,其實就是在往該線程的成員變量ThreadLocalMap中添加myThreadLocal-1的一個元素:

當我們獲取一個ThreadLocal的值myThreadLocal.get()時,其實就是從ThreadLocalMap中獲取key為myThreadLocal的entry的值:

image.png

內存泄漏

ThreadLocal使用不當是容易發生內存泄漏的。原因在于,我們設置完ThreadLocal的值后,該線程如果還在運行,ThreadLocalMap中該ThreadLocal所在的Entry不會被回收,一直在內存中存在。即存在這種引用鏈:Thread Ref -> Thread -> ThreaLocalMap -> Entry

為了解決這個問題,ThreadLocalMap中的key被設置為了弱引用,即一段時間后沒被使用的話,key值將被GC垃圾回收機制回收。而ThreadLocalget()set()執行時,會檢查ThreaLocalMap中key值為null的Entry,將value去除。

但是這仍然沒有完全解決內存泄漏的問題,原因在于,如果該線程的再也沒有執行ThreadLocalget()set()方法,則value仍然會一直存在內存中,這些key為null的Entry的value就會一直存在一條強引用鏈:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value

所以,為了避免內存泄漏,我們最好在使用完ThreadLocal后,手動remove()掉它

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容