这个问题看了很多博客,解释都是一个样, 例如这里: ,我看了一下ThreadLocal的源码 这里的Entry 是一个弱引用对象,一段时间后会被回收,回收之后这个value 的引用不也就消失了吗?何来“ThreadLocal中的key 为null,而value还存在强引用“之说?
xiao
expungeStaleEntries
get
set
remove
Thread通过中间层ThreadLocal去访问ThreadLocalMap, Map弱引用了ThreadLocal作为key。 ThreadLocal被GC但是Map中对应的Slot没有被释放。可以通过:
Map采用后者. 在set()/get()/remove()中会删除无效的slot. 这也是大多数文章提到的,然后点到为止了(??) 我猜应该是其他threadLocal调用 remove()会告诉Map去遍历删除无效的key value.
感谢!清楚多了,如果不在每次使用过后ThreadLocal.remove()的话,当前线程再次使用ThreadLocal.set()的时候会重新生成一个新的Entry (因为不能再根据key去定位到原来的Entry了,原来的Entry关联的ThreadLocal 对象由于是WeakReference 过一段时间可能被回收了,再去调用Entry.get()返回的也是null),而原来的那个Entry 相当于没用了,却还占用着内存,当这种情况发送的次数多了之后就会发送OOM! 但问题又来了,我发现只要不用WeakReference 就不存在这样的问题了?
xiao Map强引用ThreadLocal, 那么只有先回收了Map才能回收ThreadLocal. 会影响其他ThreadLocal.
xiao 我发现只要不用WeakReference 就不存在这样的问题了?
不用 WeakReference 的话,Map 会始终引用 Entry,又无法判断 Entry 是否可以回收,那才是真的内存泄露
aukocharlie 我感觉可以不用回收entry吧?每个线程维持一个Map,对每个使用的theadlocal都维护一个entry,该entry一直存在,好像也不需要多少内存吧?
准确地说是 Entry 的 value,谁知道这个 value 能有多大 😑
aukocharlie 确实,有道理!所以都是用一次创建一次并在用完之后删除
© 2018-2023 0xFFFF