使用ThreadLocal的一些注意事项
一、概述
ThreadLocal可以说是非常趁手的工具,通过它,每个线程可以独立访问自己的变量副本,利用这个特性,我们就可以用ThreadLocal来存储userId等用户信息,方便我们后续使用。不过,既然是个工具,那当然得明白怎么使用,若是使用不当就有可能导致内存泄漏问题。
二、内存泄漏问题的产生
说到这,那就得看看ThreadLocal是如何导致内存泄漏问题的。首先,前端携带token来访问受保护的资源,后端解析token没有问题,就会获取token中的载荷claims,并从claims中获取用户信息(如userId等),然后将其存入ThreadLocal中。接下来就是关键的地方了,后端在处理完请求后,如果没有清理掉ThreadLocal中的数据,并且使用的还是线程池的话,就会产生内存泄漏问题了。
为什么这样就会产生内存泄漏问题呢?主要原因还是线程池,如果使用线程池的话,平时处理请求的线程都是从线程池中拿出来的,处理完后线程又放回线程池,如果存在ThreadLocal中的数据没有清除,那就会一直在那里占用内存,导致内存泄漏,长此以往的话,就会导致内存溢出,可以说非常严重了。
三、内存泄漏问题的解决
要想解决这个问题其实不难,从上面可以发现我着重强调了没有清理掉ThreadLocal中的数据和使用线程池这两点,正是这两点的共同作用导致了内存泄漏。方法有两种,一种是每次处理完请求后清理掉ThreadLocal中的数据,另一种是不使用线程池。在我看来,就好的方法就是每次处理完请求后清理掉ThreadLocal中的数据,这样就不用管有没有使用线程池了,简单方便。
通过前面的讨论,第一种方法显而易见地看出能够解决内存泄漏,那第二种方法为什么也可以呢?如果使用第二种方法,处理请求前会创建个线程出来,使用完后将线程销毁,此时,不管有没有清理数据都没关系了,因为线程都被销毁了,那些数据自然也不复存在。
四、总结
ThreaLocal是个很好的工具,但使用不当极有可能导致内存泄漏,应在处理完请求后及时清除存入ThreaLocal中的数据,避免内存泄漏;同时应该减少 ThreadLocal 的使用频率,避免频繁读写,因为ThreadLocal 的 get() 和 set() 操作涉及哈希表查找,在高并发场景下可能影响性能。