關於ThreadLocal的使用可能造成的內存泄露以及避免方案以及爲什麼使用弱引用

我們知道,每個Thread類中有一個ThreadLocalMap類型的threadLocals變量,即每個線程中都有一個自己的map,map中的key爲ThreadLocal實例,value爲要存儲的值
在這裏插入圖片描述
我們查看該Map的結構,發現裏面有個內部類Entry,此Entry類型是構成map的結點結構,類似HashMap中的Node一樣。
在這裏插入圖片描述
我們在此發現一個問題,發現Entry中的key沒有顯式聲明,是一個ThreadLocal弱類型的引用,初始化依賴於WeakReference類,爲什麼Entry中的key要設計成弱類型的呢?

原因是:key不是弱引用將可能產生內存泄露,現在假設key設計成了強引用,在我們日常使用時,噹噹前類中Threadlocal類型不用時,理應會賦null,然後會被GC,但是由於thread中有的Entry類中key有強引用指向Threadlocal對象,所以該對象不會被回收,就造成了內存泄露,內存泄露是指本應該被回收的對象沒有被回收。

key設計成弱引用將幫助回收Entry中的key,因爲此時一但當前類中的強引用沒了,手動賦空或者類被銷燬,Threadlocal對象因爲是弱引用即將就會被gc,避免了key被無法回收的內存泄露情況,但是此時value沒有回收,還可能會造成內存泄露,JDK8中ThreadLocal爲了避免內存泄露通過 set,get,remove方法把key爲null的Entry清理掉。

使用Threadlocal時還要注意,在配合線程池使用時,不及時remove會造成內存泄露,因爲線程池中的線程始終不銷燬,單個ThreadLocal實例,在n個線程中會存在n個map,對應n個Entry,如果不及時採用remove在使用完之後移除key,將可能造成內存溢出。

所以總結出來,在使用ThreadLocal時,如果可預知的知道ThreadLocal在什麼時候不會使用時,要及時調用remove方法移除。

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