關於ThreadLocal中弱引用,以及其垃圾回收的兩個問題


1.ThreadLocalMap.Entry中的key為什么不會被錯誤清理?
    一個對象在只有弱引用指向它時,垃圾回收一旦運行,就會被回收,但是ThreadLocal對象除了在Entry中有弱引用(它的key),還在業務代碼中會被引用(否則也沒必要創建它了不是),而業務代碼中的引用一般都是強引用,所以對象如果在業務代碼中還有引用,那么即使它被弱引用指向,垃圾回收時也不會被清理。
    
2.既然有remove方法可以清理這個Entry,為什么還需要弱引用?

    remove方法確實可以解決垃圾問題,但是它只有在你調用時才會起作用(: 你在不用一個map時會去remove其中的元素嗎)。而一旦用戶忘記調用該方法,(且假如ThreadLocalMap.Entry中的key是強引用的話 ),與天地(所在線程)同壽的ThreadLocalMap中就會一直存在這么一個釘子戶,占據內存使之不能被正確回收,這種情況就可以稱為內存泄漏了。
    
    假如這個線程是個可復用線程,且它要做的每一次任務都會向ThreadLocalMap中放值,那這個垃圾堆起來可不是開玩笑的,輕則系統卡頓,重則oom。
    
    而當前的做法是,使用弱引用,即使用戶忘記調用remove方法,這個ThreadLocal對象在不用時也會被回收,一旦回收,任何對ThreadLocalMap的get和remove操作都會觸發對持有無效key的Entry的清理。這樣的話,即使你粗心大意,最多也只會在下一次垃圾回收,以及當前線程下一次操作它的ThreadLocalMap之前,允許這個Entry占一會內存。時機一到,expungeStaleEntry方法這個剃刀和gc這個推土機和配合起來,就會讓濫竽充數的無用Entry消失於無形。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM