1. 程式人生 > >31-執行緒區域性變數 ThreadLocal

31-執行緒區域性變數 ThreadLocal

  1. 執行緒區域性變數 ThreadLocal
    1. 原理,作用

每個Thread維護一個ThreadLocalMap 對映表,使用ThreadLocal物件為弱引用的map集合(即弱引用的物件可以在GC中被回收掉),value為對應的值。其生命週期和執行緒一致。

作用:提供執行緒內的區域性變數;線上程的生命週期內起作用,減少同一個執行緒內多個函式或者元件之間一些公共變數的傳遞的複雜度。

    1. 用法
      1. initialValue():

當get()方法為null時,內部執行開始呼叫initialValue()方法;當執行完remove()方法,在下一次呼叫get()方法(獲取的為null)時,內部執行開始呼叫initialValue()方法。

        1. 原始碼分析

      1. get(): 獲取ThreadLocal中當前執行緒共享變數的值。
        1. 原始碼分析

      1. set(t): 設定ThreadLocal中當前執行緒共享變數的值。
        1. 原始碼分析

      1. remove(): 移除ThreadLocal中當前執行緒共享變數的值。
        1. 原始碼分析

      1. ThreadLocalMap
        1. private Entry[] table;
        2. private int size = 0;
        3. static class Entry extends WeakReference<ThreadLocal> {

            Object value;

            Entry(ThreadLocal k, Object v) {super(k);value = v;}}

 

    1. 案例

    1. 弱引用
      1. 弱引用導致的記憶體洩露

當執行緒沒有結束,但是ThreadLocal已經被回收,則可能導致執行緒中存在ThreadLocalMap<null, Object>的鍵值對。如果執行緒遲遲不能結束,則key為null的Entry的value不能被回收掉。

雖然其get(),set(),remove()在呼叫的時候,會自動清除執行緒ThreadLocalMap裡所有key為null的value,但不能確保不會發生記憶體洩露。

      1. 使用弱引用的原因

如果key 使用強引用,在引用的ThreadLocal的物件被回收時,由於ThreadLocalMap持有ThreadLocal的強引用;如果沒有手動刪除,ThreadLocal不會被回收,導致Entry記憶體洩漏;

而採用弱引用,在在引用的ThreadLocal的物件被回收時,可自動回收ThreadLocal。

      1. 記憶體洩露的處理方法

1、使用完執行緒共享變數後,顯示呼叫ThreadLocalMap.remove方法清除執行緒共享變數;

2、JDK建議ThreadLocal定義為private static,這樣ThreadLocal的弱引用問題則不存在了。