DIY主題討論12:ThreadLocal的問題根源

DIY主題討論12:ThreadLocal的問題根源

ThreadLocal理解

  1. ThreadLocal意義:實現對象在線程內的透傳,可以跨類跨方法傳遞數據
  2. ThreadLocal變量的定義:
    ThreadLocal變量必須定義爲static,非static的threadLocal也就失去了跨類跨方法傳遞數據的能力。
private static final ThreadLocal<T> threadLocal=new ThreadLocal<>();
  1. ThreadLocal值存儲位置:
    ThreadLocal類內部有ThreadLocalMap靜態內部類,ThreadLocalMap還有一個靜態內部類Entity,ThreadLocal的值實際上存儲在ThreadLocalMap的Entity中。但是ThreadLocalMap是線程Thread的成員變量,也就是說ThreadLocal的值實際上是存在Thread對象中。

ThreadLocal內部結構理解

問題1:ThreadLocal如何回收value,什麼時候回收?

因爲ThreadLocal使用的時候,ThreadLocal對象要被設置爲static類型,也就是不會隨着線程的銷燬而銷燬。
進一步理解ThreadLocalMap的Entity,Entity繼承自WeakReference,Entity便具有弱引用的特性,爲何使用弱引用,原意是希望ThreadLocal對象消失時,線程對象持有的這個ThreadLocal不再有意義,應該隨着GC回收。Entity是鍵值對形式,key是ThreadLocal對象,value是實際的值,但是ThreadLocal對象是static類型,因此即使在線程銷燬後,entity的key引用ThreadLocal對象,因爲ThreadLocal對象一直存在導致entity不能被回收,造成內存泄漏。
正確用法:在ThreadLocal的value使用完後,調用ThreadLocal對象的remove方法,顯式移除,回收value。

問題2:ThreadLocal爲什麼會產生髒數據?

ThreadLocal產生髒數據主要發生在線程複用的場景下,也就是在使用線程池複用線程時要注意髒數據問題。
髒數據產生的原因:ThreadLocal的變量實際是存儲在ThreadLocalMap中,而ThreadLocalMap是線程Thread的成員變量,因此當一個線程被線程池複用,ThreadLocalMap也會被複用,這時如果上一個線程使用時候的ThreadLocalMap值沒有被清除,就會產生髒數據。

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