多线程中ThreadLocal踩坑

2018-08-01  本文已影响0人  FujianSun

前言

记录一下在测试过程中,遇到的一个有关ThreadLocal的问题,顺便学习一下ThreadLocal相关的知识。

ThreadLocal介绍

ThreadLocal是一个关于创建线程局部变量的类。

要点:

问题场景

最近项目需要上线一个大版本,此次版本对前端APP新、老版本发起的请求做了不同的加密处理,经过讨论,需要在后台做版本兼容。

兼容的流程:

问题描述

按照上面的兼容流程做完代码更改之后,在本地测试没有问题,但是放在测试环境,由测试人员测试就有问题。

具体问题描述:

分析结果

我们知道,后端应用服务器在处理请求时,会对每一个请求分配一个线程来处理,如果每次来一个请求都去新开一个线程,然后响应请求之后又去销毁线程,这样的结果不仅会增加请求响应时间,而且还会大大提高系统资源消耗。

所以为了适应高并发请求,在应用服务器端都会使用线程池来处理请求,效果是减少系统资源开销以及加快请求响应时间。

前面讲到,由于ThreadLocal是以当前线程为key,所以如果前后有两条请求发到后台,并且这两条请求都是使用的线程池里面的同一个线程。并且第一条是新版本APP发过来的带有标识的请求,第二条是老版本APP发过来的不带标识的请求。

第一条请求把标识存入ThreadLocal变量中,在响应完请求之后没有及时的清理掉ThreadLocal中的值

当第二条不带标识的请求到来时,由于在SpringDispatcherServlet中做了不为空才把标识放入ThreadLocal中,所以这里就没有更新ThreadLocal中的值,但其实由于前面一个请求响应之后没有清理掉ThreadLocal中的值,所以在JsonHttpMessageConverter中获取当前线程的标识时,还是有值,这样就会进入新版本的解密方式中去。

问题处理

两种方式:

最后我采取的第二种方式,因为按逻辑是ThreadLocal里面的数据只适合在本次请求中使用,使用完了之后就得清理掉

上一篇下一篇

猜你喜欢

热点阅读