ThreadLocal使用之后切记一定要执行remove方法

一.问题

在使用ThreadLocal做线程间数据传递的过程中,发现有的用户数据出现了异常

二.分析问题

1.理论上来说ThreadLocal是线程安全的
2.只有在暴露ThreadLocal数据时多线程对其修改,或者内存溢出才会导致线程安全问题
3.知道这些先来看一下具体业务代码

a.这是一个导出Excel任务
b.监听查询任务,如果任务超时,则异步执行
c.由于Session的问题所以采用ThreadLocal进行线程间数据传输
在这里插入图片描述

在这里插入图片描述

似乎没有什么问题,但是有些用户的权限似乎出现了问题,并且是偶发性的,然后定位到了这段代码,因为查询操作从头到尾没有使用过TheadLocal中的信息,理论上来说这里的requestSession这个Map一定是null,但是在后续的debug中发现查询操作居然进入了第一个判断

在这里插入图片描述

三.原因猜测

  1. 从上面的分析可以看出来,查询操作没有使用到ThreadLocal,但是其中却有数据,说明是在其他地方进行了set操作
  2. 然后仔细检查了所有的拦截器,是否存在使用了ThreadLocal的情况,最终没有发现
  3. 自此就非常奇怪了,ThreadLocal线程安全,所以理论上线程见的数据不会相互影响

在这里插入图片描述

  1. 查看ThreadLocal的set源码,这里感觉非常的奇怪,ThreadLocal是使用当前线程作为key,然后返回了一个ThreadLocalMap,然后将数据写了进去,这让我感到非常的奇怪,那如果有用户当前线程的名称一样,那线程不就不安全了吗,所以这个问题就变成了SpringMVC是否会复用线程?

  2. 这里写了个demo

在这里插入图片描述

执行第一个请求10次之后,发现SpringMVC开始复用线程了,这让我很吃惊,这时候请求第二个接口,发现居然从ThreadLocal中取到了数据,SpringMVC这么做自然是为了避免资源的浪费

在这里插入图片描述

四.总结

  1. ThreadLocal确实是线程安全的,但是和SpringMVC配合使用的时候,springMVC复用了线程,导致ThreadLocal不再线程安全
  2. 在使用完ThreadLocal之后一定要执行remove方法,不管任务知否执行成功
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值