ThreadLocal对象帮助我们管理线程内的对象,保证对象在线程之间是相互隔离的。

今天碰到的坑是这样的:

index01.html页面加载的时候会发送一次a请求,然后点击附件上传的时候会发送上传请求b,上传成功后会发送下载请求c,

其中a请求会经过interceptor01拦截器,interceptor01内部会将a请求传递的module_name参数存入本地线程变量,b请求不会经过拦截器,c请求会经过拦截器,但是不会传递module_name,这时线程变量会存入一个空的module_name。

具体现象是这样的,进入index01.html页面,第一次点击上传附件后,下载附件可以成功,但是只要不关闭浏览器重新打开页面,后续点击的所有上传请求都不能成功,并且报module_name为空的错,module_name是从本地线程变量中获取的。

因此怀疑是不是module_name参数没有存入本地线程,经过几番查询发现,b请求不经过拦截器,所以b请求中拿不到module_name是正常的,但是奇怪的是,b请求竟然能够拿到本地线程变量中的其它的属性值,真实百思不得其解,因为可以确定,线程变量只有在拦截器interceptor01中才会初始化并赋值!

让我们再梳理一下,b请求没有经过拦截器,那么本地线程变量就没有初始化,但是在b请求中取本地线程变量的时候,竟然能取到,只是唯独module_name取不到。

好吧,可以肯定线程变量只能在本线程中获取到,那么只有一个解释,那就是b请求与别的请求共用了同一个线程!换句话说,并不是每一个请求,web容器都会使用不同的线程来处理。为了证实这一想法,我将a、b、c请求的Threadid打印出来比对,发现果然是一样的。

这就可以解释上述的问题了:

当我们第一次进入index01.html页面,a请求会经过拦截器,然后初始化线程变量,存入module_name;

接着b请求不会经过拦截器,但是由于和a请求使用的是同一个线程,所以能够正常取出module_name,并成功上传;

接着c请求会经过拦截器,但是不会传递module_name,所以把线程中的module_name就置空了;

最后当我们再次上传发送b请求的时候,线程中就没有module_name了。

下面说说为什么3个请求会共用一个线程,2个原因:

1、http1.1协议中的keep-alive是默认开启的,同一个会话中,有限的请求是共用一个长连接的。

2、tomcat默认使用线程池,所以一个线程的生命周期不能对等于一个请求的生命周期,线程池中的线程是可以被复用的。

解决方案:

1、保证每次都用新的值覆盖线程变量;

2、保证在每个请求结束后清空线程变量。

ThreadLocal对象使用过程中容易陷入的坑的更多相关文章

  1. APP store 上架过程中碰到的那些坑&被拒的各种奇葩原因整理&审核指南中文版

    苹果官方发布的十大常见被拒原因 1.崩溃次数和Bug数量.苹果要求开发者在将应用提交给App Store之前彻查自己的应用,以尽量避免Bug的存在. 2.链或错误的链接.应用中所有的链接必须是真实且有 ...

  2. 使用ffmpeg视频编码过程中踩的一个坑

           今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,非常多时候一旦思维定势真的挺难突破的.以下是不对的编码结果:                   ...

  3. SpringCloud整合过程中jar依赖踩坑经验

    今天在搭建SpringCloud Eureka过程中,一直在报pom依赖错误,排查问题总结如下经验. 1.SpringBoot整合SpringCloud两者版本是有严格约束的,详细见SpringBoo ...

  4. 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理

    原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...

  5. 谈谈使用echarts过程中踩过的坑

    小结: 1. 使用jquery获取json对象遇到的问题 由于自己对ajax用的还不熟练,之前都是拷贝别人的代码拿来用的,这次自己写的时候倒是碰到好多麻烦一一列举如下: 1.1 在$ 与ajax之间还 ...

  6. Deep Q-Network 学习笔记(一)—— Q-Learning 学习与实现过程中碰到的一些坑

    这方面的资料比较零散,学起来各种碰壁,碰到各种问题,这里就做下学习记录. 参考资料: https://morvanzhou.github.io/ 非常感谢莫烦老师的教程 http://mnemstud ...

  7. 【spring】使用spring过程中踩到的坑

    这里简单记录一下,学习spring的时候碰过的异常: 异常:org.springframework.beans.factory.BeanDefinitionStoreException: Unexpe ...

  8. [Appium] 使用Appium过程中遇到的各种坑

    以下问题都是以ios为背景: 1. 问题: Case: 在页面S1上,点击元素A后,判读B元素是否出现. Detail:一开始通过Appium Inspector, 可以找到B元素,所以直接取该元素的 ...

  9. NetCore部署到Linux服务器+Supervisor的步骤及过程中踩过的坑

    本文作备忘使用 服务器配置: 下面是所有操作的具体步骤: 1.安装nginx   参考 1.1 添加源:默认情况Centos7中没有Nginx源,最近Nginx官网提供了Centos的源地址. sud ...

随机推荐

  1. Web服务器与数据库服务器分离 导入 Excel数据至数据库

    一般情况一般项目WEB服务器与数据库均部署在一台服务器,文件上传,数据导入在一台服务器完成.web服务器与数据库服务器分离,文件上传与数据导入将分布在两台服务器或多台服务器之间.本案例为两台服务器,具 ...

  2. Java 知识结构图

    不可不懂的.NET基础知识 - 谷海燕 - 博客频道 - CSDN.NEThttp://blog.csdn.net/zhuanzhe117/article/details/8954924 出处:深入理 ...

  3. Django框架-目录文件简介

    Rhel6.5 Django1.10 Python3.5 Django框架-目录文件简介 1.介绍Django Django:一个可以使Web开发工作愉快并且高效的Web开发框架. 使用Django, ...

  4. 修复win10升级时断电inaccessible boot device

    代码提示0xc0000001 这里的解决方法对系统以及个人的没有文件丢失的影响,没有重装以及重置上丢失东西的顾虑 解决方法: WINDOWS/system32/config/RegBack/SYSTE ...

  5. Oracle Database 12c Release 1下载安装(自身经历)

    1.访问Oracle官网:https://www.oracle.com/index.html,下载Oracle Database 12c Release 1 (注意:File1和File2都要下载!! ...

  6. 【转】理解 PHP 依赖注入 | Laravel IoC容器

    Laravel框架的依赖注入确实很强大,并且通过容器实现依赖注入可以有选择性的加载需要的服务,减少初始化框架的开销,下面是我在网上看到的一个帖子,写的很好拿来与大家分享,文章从开始按照传统的类设计数据 ...

  7. 解决CURL 请求本地超时

    首先,这样的问题只会出现在Windows+Nginx中. php-cgi 默认使用的是9000端口,即使多个进程也并发的是9000端口 在用户访问一个php页面的时候nginx已将该进程占用,在该进程 ...

  8. 查看文本[Linux]

    查看文本 不分屏查看 cat (默认标准输入到标准输出) -n(行号) 连接...并显示 -E(每行行尾打印$) 翻屏:shift+pageUp/pageDown tac reverse cat 分屏 ...

  9. 白银5kg

    领悟: 1.其实大势涨也好,跌也好,如果我们知道价格到哪里会受阻或反弹,能出有出利润的空间,我们就可以做单.

  10. Nginx - Linux下按天分割日志

    待完善. 可参考:https://www.iteblog.com/archives/1244