ThreadLocal对象使用过程中容易陷入的坑
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对象使用过程中容易陷入的坑相关推荐
- 找对象的过程中,我竟然理解了什么是机器学习!
最近开始了有关机器学习方面知识的学习,自己啃书本的时候一些概念枯燥无味,所以借着做笔记的机会来简单理解其中的一些概念,如有谬误,还望指出.? 什么是人工智能? 我看过很多博客解释什么是人工智能,我觉得 ...
- 探讨:在Mac新系统下安装新版XAMPP过程中遇到到的坑以及解决办法
探讨:在Mac新系统下安装新版XAMPP过程中遇到到的坑以及解决办法 简介 XAMPP安装 XAMPP 是个啥? 安装XAMPP 新版问题:IP地址访问不再是localhost 操作问题:apache ...
- Centos7+mysql57+python3安装过程中踩过的坑
Centos7+mysql57+python3安装过程中踩过的坑 说明: 为了练习Django项目,准备在虚拟机中安装Centos7+mysql57+python3.在windows环境下通过Navi ...
- @Value注解使用过程中遇到的一些坑
笔者结合之前的一些经验教训,再结合一些资料总结了一下@Value注解使用过程中的一些注意事项. 目录 一.@Value无法读取配置文件中的参数 二.@Value出现中文乱码 三.@Value使用的一些 ...
- azkaban的部署过程中遇到的一些坑(部署篇)
2019独角兽企业重金招聘Python工程师标准>>> 1.azkaban源码下载 maven下载地址3.0.0版本:https://gitee.com/wenhaijin_830_ ...
- Android Studio安装使用过程中踩到的坑
首先在整成安装的过程中,会弹出一句话,Unable to access Android SDK add-on list,意思是无法访问Android SDK加载项列表 此时,你点击Cancel选项即可 ...
- 从vue文件中抽取出子组件的流程及过程中踩过的坑
流程: 1. 确保注册.引入子组件的正确性: 创建一个新的vue文件,包含基本的template,及export的内容,其中可简单包含空的data函数.暂时先不把子组件中的代码移出.在父组件中impo ...
- libx264编码过程中修改码率踩坑记录
问题来源于项目中的一个需求,根据当前网络环境实时调整libx264的码率参数,从而让视频播放更加流畅. 1.设置码率调整算法为ABR. 2.初始化,并提供一个接口供探测网络环境的线程调用.写法大概类似 ...
- 服务器安装Windows Server 2008 R2系统过程中遇到的一些坑
最近客户的一台安装了Windows Server 2008 R2操作系统的服务器老是蓝屏死机,这时候服务器的负载比较高.蓝屏代码如下: 由上图可知,蓝屏代码为0x000000c5,网上搜索大多数都说是 ...
- 程序员、工程师使用mac电脑过程中遇到的各种坑汇总
由于mac电脑的电源待机时间超长,操作便利,系统响应快,超能的命令行,便于携带,越来越多程序猿们开始从windows转向mac.鉴于目前大部分应用都是先有windows版本,然后再开发mac版本,因此 ...
最新文章
- java弹出网页alter_JavaScript三种弹出框(alert,confirm和prompt)用法举例
- 什么叫取反_转载:CodeReview正确的姿势是什么?
- Lammps 问题集锦
- 使用基于注解的mybatis时,利用反射和注解生成sql语句
- 深度学习(五)caffe环境搭建
- 53、shell常用快捷方式
- New %: % Syntax for HTML Encoding Output in ASP.NET 4 (and ASP.NET MVC 2)
- 大学阶段总结——大三
- 赶集网MySQL开发36军规
- CentOS密码忘记后的操作
- from mysql_MySQL的FROM
- 只需四步完成java JDK1.8的下载安装与配置【图文详解】
- Spark执行任务卡死:SparkException: Failed to connect to driver! unable to launch application master
- java高级流程控制多线程作业设计_Java高级-解析Java中的多线程机制
- 汉明码---存储器校验(简单易懂详解)
- 2016CCPC长春:Sequence II(主席树)
- arduino和python对接_Python:与Arduino进行交互-后续
- 2.70-写出具有如下原型的函数的代码:
- 【树莓派】USB摄像头+python+opencv
- c语言二进制强制转十六进制,C语言二进制转十六进制问题
热门文章
- springMVC简易学习笔记一
- golang 生成定单号
- 使用 lanmps 环境套件安装设置新站点 案例
- Spring Boot @ServletComponentScan 扫描 @WebServlet、@WebFilter、@WebListener
- android activity使用,Android Activity使用拾遗
- 集合代码----小练习3
- ubuntu 在线安装最新交叉编译工具
- python之OrderedDict类
- 从运行原理及使用场景看Apache和Nginx
- thinkphp3.2.3入口文件详解