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、保证在每个请求结束后清空线程变量。

转载于:https://www.cnblogs.com/anai/p/5620705.html

ThreadLocal对象使用过程中容易陷入的坑相关推荐

  1. 找对象的过程中,我竟然理解了什么是机器学习!

    最近开始了有关机器学习方面知识的学习,自己啃书本的时候一些概念枯燥无味,所以借着做笔记的机会来简单理解其中的一些概念,如有谬误,还望指出.? 什么是人工智能? 我看过很多博客解释什么是人工智能,我觉得 ...

  2. 探讨:在Mac新系统下安装新版XAMPP过程中遇到到的坑以及解决办法

    探讨:在Mac新系统下安装新版XAMPP过程中遇到到的坑以及解决办法 简介 XAMPP安装 XAMPP 是个啥? 安装XAMPP 新版问题:IP地址访问不再是localhost 操作问题:apache ...

  3. Centos7+mysql57+python3安装过程中踩过的坑

    Centos7+mysql57+python3安装过程中踩过的坑 说明: 为了练习Django项目,准备在虚拟机中安装Centos7+mysql57+python3.在windows环境下通过Navi ...

  4. @Value注解使用过程中遇到的一些坑

    笔者结合之前的一些经验教训,再结合一些资料总结了一下@Value注解使用过程中的一些注意事项. 目录 一.@Value无法读取配置文件中的参数 二.@Value出现中文乱码 三.@Value使用的一些 ...

  5. azkaban的部署过程中遇到的一些坑(部署篇)

    2019独角兽企业重金招聘Python工程师标准>>> 1.azkaban源码下载 maven下载地址3.0.0版本:https://gitee.com/wenhaijin_830_ ...

  6. Android Studio安装使用过程中踩到的坑

    首先在整成安装的过程中,会弹出一句话,Unable to access Android SDK add-on list,意思是无法访问Android SDK加载项列表 此时,你点击Cancel选项即可 ...

  7. 从vue文件中抽取出子组件的流程及过程中踩过的坑

    流程: 1. 确保注册.引入子组件的正确性: 创建一个新的vue文件,包含基本的template,及export的内容,其中可简单包含空的data函数.暂时先不把子组件中的代码移出.在父组件中impo ...

  8. libx264编码过程中修改码率踩坑记录

    问题来源于项目中的一个需求,根据当前网络环境实时调整libx264的码率参数,从而让视频播放更加流畅. 1.设置码率调整算法为ABR. 2.初始化,并提供一个接口供探测网络环境的线程调用.写法大概类似 ...

  9. 服务器安装Windows Server 2008 R2系统过程中遇到的一些坑

    最近客户的一台安装了Windows Server 2008 R2操作系统的服务器老是蓝屏死机,这时候服务器的负载比较高.蓝屏代码如下: 由上图可知,蓝屏代码为0x000000c5,网上搜索大多数都说是 ...

  10. 程序员、工程师使用mac电脑过程中遇到的各种坑汇总

    由于mac电脑的电源待机时间超长,操作便利,系统响应快,超能的命令行,便于携带,越来越多程序猿们开始从windows转向mac.鉴于目前大部分应用都是先有windows版本,然后再开发mac版本,因此 ...

最新文章

  1. java弹出网页alter_JavaScript三种弹出框(alert,confirm和prompt)用法举例
  2. 什么叫取反_转载:CodeReview正确的姿势是什么?
  3. Lammps 问题集锦
  4. 使用基于注解的mybatis时,利用反射和注解生成sql语句
  5. 深度学习(五)caffe环境搭建
  6. 53、shell常用快捷方式
  7. New %: % Syntax for HTML Encoding Output in ASP.NET 4 (and ASP.NET MVC 2)
  8. 大学阶段总结——大三
  9. 赶集网MySQL开发36军规
  10. CentOS密码忘记后的操作
  11. from mysql_MySQL的FROM
  12. 只需四步完成java JDK1.8的下载安装与配置【图文详解】
  13. Spark执行任务卡死:SparkException: Failed to connect to driver! unable to launch application master
  14. java高级流程控制多线程作业设计_Java高级-解析Java中的多线程机制
  15. 汉明码---存储器校验(简单易懂详解)
  16. 2016CCPC长春:Sequence II(主席树)
  17. arduino和python对接_Python:与Arduino进行交互-后续
  18. 2.70-写出具有如下原型的函数的代码:
  19. 【树莓派】USB摄像头+python+opencv
  20. c语言二进制强制转十六进制,C语言二进制转十六进制问题

热门文章

  1. springMVC简易学习笔记一
  2. golang 生成定单号
  3. 使用 lanmps 环境套件安装设置新站点 案例
  4. Spring Boot @ServletComponentScan 扫描 @WebServlet、@WebFilter、@WebListener
  5. android activity使用,Android Activity使用拾遗
  6. 集合代码----小练习3
  7. ubuntu 在线安装最新交叉编译工具
  8. python之OrderedDict类
  9. 从运行原理及使用场景看Apache和Nginx
  10. thinkphp3.2.3入口文件详解