ThreadLocal 記憶體洩漏

2021-10-08 14:25:44 字數 1661 閱讀 2892

個人對記憶體洩漏的理解:如果乙個我用不到物件一直在記憶體裡,那麼就出現記憶體洩漏了。

簡單說一下theadlocal實現原理:

通過執行緒私有的空間來儲存資料,即在thread類裡有乙個threadlocalmap型別的變數:

/* threadlocal values pertaining to this thread. this map is maintained

* by the threadlocal class. */

threadlocal.threadlocalmap threadlocals = null;

threadlocal.threadlocalmap就是乙個map,內部使用了乙個entry型別的陣列來儲存資料:
static class entry extends weakreference> 

}

從原始碼上看,entry是繼承弱引用weakreference的,k對於entry就是乙個弱引用,如果k不存在強引用,那麼它將會被**,此時entry的k是空。

乙個關鍵資訊:entry的k就是乙個threadlocal物件,threadlocal相對於entry來說就是乙個弱引用。

theadlocal物件如果在外部不存在強引用,那麼對應entry的k將會被**掉,有部分文章認為此時如果不呼叫threadlocal#remove()方法,將會出現entry和value不會被**掉,從而出現記憶體洩漏。但我認為此時不一定出現記憶體洩漏的,因為threadloocal有乙個cleansomeslots方法,它會把key==null的entry給**掉。測試:

public static void main(string args) throws exception  

system.out.println(getthreadlocalmapsize());

} /** 獲取entry的數量 */

private static int getthreadlocalmapsize() throws exception

執行完成後,主線程的threadlocalmap的entry的size遠遠小於100000。證明threadlocalmap中的無效entry會被自動**。

這種情況也是會有記憶體洩漏的風險,因為cleansomeslots方法依賴於下一次get、set、remove方法呼叫,如果get、set、remove方法再也沒有被呼叫過,那麼此時對應entry也不會被**掉,從而導致記憶體洩漏。

另外一種情況就是申明乙個是全域性的threadlocal變數:

public static final threadlocal threadlocal = new threadlocal();
此時threadlocal就會被所有執行緒所共享,它一直都將會是乙個強引用,導致entry的k一直得不到**從而記憶體洩漏(實際上可能此時我的執行緒已經不需要這個threadlocal了),更好的做法是如果當前執行緒確定不會用到這個threadlocal,就手動調動threadlocal#remove方法,remove方法會將當前執行緒的threadlocalmap中對應entry給**掉。

總結:如果我們能確定我們的執行緒不會再用到threadlocal了,就手動呼叫threadlocal#remove以避免記憶體洩漏!

ThreadLocal記憶體洩漏

重新上傳 取消threadlocal threadlocal的實現是這樣的 每個thread維護乙個threadlocalmap對映表,這個對映表的key是threadlocal例項本身,value是真正需要儲存的object。也就是說threadlocal本身並不儲存值,它只是作為乙個key來讓執...

ThreadLocal 記憶體洩漏

theadlocal 記憶體洩漏的根源是 由於threadlocalmap的生命週期跟thread一樣長,如果沒有手動刪除對應的key就會導致記憶體洩漏,而不是因為弱引用 一 threadlocalmap的 key 為 threadlocal 弱引用 二 threadlocal正確的使用方法 1 每...

ThreadLocal 記憶體洩漏問題

threadlocal 實現原理 threadlocal為什麼會記憶體洩漏 threadlocal 最佳實踐 threadlocal 實現原理 threadlocal的實現是這樣的 每個thread 維護乙個 threadlocalmap 對映表,這個對映表的 key 是 threadlocal例項...