ThreadLocal的脏数据、内存泄露

2023-05-16

背景:

Spring-Boot 2.0.8.RELEASE

Spring-Cloud 2.0.4.RELEASE

tomcat 8.5.37

JDK 1.8

项目使用ThreadLocal来传递参数,比如:请求数据、设置变量

ThreadLocalParamsUtil
public class ThreadLocalParamsUtil {
	private static final Log log = LogFactory.getLog(ThreadLocalParamsUtil.class);

	private static final ThreadLocal<Map<String,Object>> threadLocalMap=new ThreadLocal<>();

    public static <T>T get(String key){
        // 。。。
    }
    
    public static void set(String key, Object value) {

    }

    public static void clean(String key) {
    
    }
    
    public static void cleanAll() {

    }

      接口正常返回时,调用ThreadLocalParamsUtil.cleanAll()清除了所有的共享变量。

      接口处理过程发生异常的时候,并没有调用ThreadLocalParamsUtil.cleanAll()清除所有的共享变量。

问题:

      在接口的处理过程中,ThreadLocalParamsUtil.get("myKey"),有时候获取到的值是脏数据,导致程序处理出现异常。

模拟场景:(实际的发生场景其实是比较复杂的,这里简化了下)

      当接口处理过程发生了异常之后,由于没有清除共享变量,导致该线程的线程内共享变量一直存在着,发生了内存泄露和脏数据。

      当后续的请求使用的是这个发生过异常的线程的时候,ThreadLocalParamsUtil.get("myKey")就会获取到上次该线程的请求的时候设的值,也就是脏数据。

      为什么不是每次都获取到脏数据呢?因为tomcat处理请求的时候使用的是线程池,默认的核心线程数是10,那么可能经过10次请求之后,就会有一次获取到脏数据,导致程序处理异常。

使用注意事项

    ThreadLocal线程内共享变量,方便是方便,但是要注意每次set后,在不需要使用到该key的时候,一定要remove清理掉,否则不仅是造成内存泄露,还可能导致脏数据的产生,从而出现一些奇奇怪怪的错误。

注:springboot内置tomcat的线程池:(参考:https://blog.csdn.net/qq_31086797/article/details/110523079)

参数
线程池核心线程数
server.tomcat.min-spare-threads:该参数为tomcat处理业务的核心线程数大小,默认值为10

线程池最大线程数
server.tomcat.max-threads:该参数为tomcat处理业务的最大线程数大小,默认值为200,当对并发量有一点值时可以调大该参数

请求最大连接数
server.tomcat.max-connections:该参数为请求的最大连接数,默认值为10000,注意这个参数并不是设置在线程池上的,而是在tomcat的Acceptor类(专门处理连接的线程类)来控制的
 

   

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ThreadLocal的脏数据、内存泄露 的相关文章

随机推荐