爆资讯爆资讯爆资讯

面试官:说说ThreadLocal的内存泄露

ThreadLocal的内存泄露

什么是内存泄漏和内存溢出

我们在讲ThreadLocal的内存泄漏之前,首先要搞清楚什么是内存泄漏,那要说起内存泄漏,肯定还有个概念需要说,那就是内存溢出,这两者是个啥呢?

首先什么是内存泄漏:

说的简单点那就是因为操作不当或者一些错误导致没有能释放掉已经不再使用的内存,这就是内存泄漏,也就是说,有些内存已经不会再使用了,但是却没有给它释放掉,这就一直占用着内存空间,从而导致了内存泄漏。

那什么是内存溢出呢?

这个简单点说就是内存不够用了,我运行一个程序比如说需要50M的内存,但是现在内存就剩下20M了,那程序运行就会发生内存溢出,也就是告诉你内存不够用,这时候程序就无法运行了。

好,了解了基本概念之后,我们再来看看T和read Local的内存泄漏,那为什么T和read Local会产生内存泄漏呢?我们再来看看这张图:

面试官:说说ThreadLocal的内存泄露

经过我们上述的讨论,我们大致知道了ThreadLocal其实本质上是在每个线程中单独维护了一个ThreadLocalMap数据结构,这个ThreadLocalMap是每个线程独有的,只有根据当前线程才能找到当前线程的这个ThreadLocalMap,这就实现了线程之前的隔离。

我们看上面那张图,每个线程根据找到自己维护的ThreadLocalMap,然后可以操作这个数据结构,往里面存取数据,而ThreadLocalMap中维护的就是一个Entry数组,每个Entry对象就是我们存放的数据,它是个key-value的形式,key就是ThreadLocal实例的弱引用,value就是我们要存放的数据,也就是一个ThreadLocal的实例会对用一个数据,形成一个键值对。

如果有两个线程,持有同一个ThreaLocal的实例,这样的情况也就是Entry对象持有的ThreadLocal的弱引用是一样的,但是两个线程的ThreadLocalMap是不同的,记住一点,那就是ThreadLocalMap是每个线程单独维护的。

为什么会出现内存泄漏

那我们现在来看,为什么ThreadLocal会出现内存泄漏,我们之前也说过了,Entry对象持有的是键就是ThreadLocal实例的弱引用,弱引用有个什么特点呢?那就是在垃圾回收的时候会被回收掉,可以根据上图想一下,图中虚线就代表弱引用,如果这个ThreadLocal实例被回收掉,这个弱引用的链接也就断开了,就像这样:

面试官:说说ThreadLocal的内存泄露

那么这样在Entry对象中的key就变成了null,所以这个Entry对象就没有被引用,因为key变成看null,就取不到这个value值了,再加上如果这个当前线程迟迟没有结束,ThreadLocalMap的生命周期就跟线程一样,这样就会存在一个强引用链,所以这个时候,key为null的这个Entry就造成了内存泄漏。

因为它没有用了,但是还没有被释放。

如何解决内存泄漏

明白了如何产生的内存泄漏,也就知道了怎么解决,经过上面的分析,我们大致知道了在ThreadLocalMap中存在key为null的Entry对象,从而导致内存泄漏,那么只要把这些Entry都给删除掉,也就解决了内存泄漏。

我们每次使用ThreadLocal就会随线程产生一个ThreadLocalMap,里面维护Entry对象,我们对Entry进行存取值,那么如果我们每次使用完ThreadLocal之后就把对应的Entry给删除掉,这样不就解决了内粗泄漏嘛,那怎么做呢?

在ThreadLocal中提供了一个remove方法:

面试官:说说ThreadLocal的内存泄露

这个就是根据key删除掉对应的Entry,如此一来,我们就解决了内存泄漏问题,因为可能出现内存泄漏的Entry,在我们使用完之后就立马删除了。

所以对于ThreadLocal而言,就应该像使用锁一样,加锁之后要记得解锁,也就是调用它的remove方法,用完就清理。


总结

ThreaLocalMap中存储的核心元素是Entry,Entry是一个弱引用,所以在垃圾回收的时候,ThreadLocal如果没有外部的强引用,它会被回收掉,这样就会产生key为null的Entry了,这样也就产生了内存泄漏。

在ThreadLocal的get(),set()和remove()的时候都会清除ThreadLocalMap中key为null的Entry,如果我们不手动清除,就会造成内存泄漏,最佳做法是使用ThreadLocal就像使用锁一样,加锁之后要解锁,也就是用完就使用remove进行清理。

认真写文章,用心做分享。
公众号:Java耕耘者

未经允许不得转载:爆资讯 » 面试官:说说ThreadLocal的内存泄露

相关推荐