ThreadLocal 在web环境下使用的边界问题
2015-10-20 13:41
309 查看
ThreadLocal 相关分析,请查看/content/2593696.html
另外一个必须要提的点是:
ThreadLocal在线程池环境下的使用。
比如tomcat 提供的web http请求,一般都有线程池对请求做处理。
这种情况下要注意,并非每次web请求时候程序运行的ThreadLocal都是唯一的,ThreadLocal的生命周期不等于一次Request的生命周期,ThreadLocal与线程对象紧密绑定的,由于Tomcat使用了线程池,线程是可能存在复用情况,这时的ThreadLocal 的使用要谨慎使用。
web请求下 的ThreadLocal 使用要保证:请求进来的时候set,请求回去的时候remove。只有这样才能保证请求内的ThreadLocal 是唯一的。 这个特性在深刻的提醒我们:一次http请求和tomcat启动处理业务的线程并非一一对应的,而是通过一个线程池进行调度。
错误的使用案例:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/cd5533d788416a7bc2d665e7c6782adc.png)
@Controller
public class ThreadLocalController {
private static final ThreadLocal<Integer> id = new ThreadLocal<Integer>();
@ResponseBody
@RequestMapping("/threadLocalTest")
public Map<String, Object> threadLocalTest() {
Integer myId = id.get();
if (myId == null) {
id.set(1);
} else {
id.set(id.get() + 1);
}
System.out.println(id.get());
Map<String, Object> retMap = new LinkedHashMap<String, Object>();
retMap.put("id", id.get());
return retMap;
}
}
以上代码运行的时候会发现,命令行打印的id 是不确定的,这时因为tomcat本身对请求做线程池缓存业务处理线程导致的。
正确的使用案例:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/cd5533d788416a7bc2d665e7c6782adc.png)
@Controller
public class ThreadLocalController {
private static final ThreadLocal<Integer> id = new ThreadLocal<Integer>();
@ResponseBody
@RequestMapping("/threadLocalTest")
public Map<String, Object> threadLocalTest() {
Integer myId = id.get();
if (myId == null) {
id.set(1);
} else {
id.set(id.get() + 1);
}
System.out.println(id.get());
Map<String, Object> retMap = new LinkedHashMap<String, Object>();
retMap.put("id", id.get());
id.remove();
return retMap;
}
}
以上代码每次输出的都是1,注意id.remove() 方法的调用,在每次请求结束的时候remove对象。
更多的情况下,做为系统级别的,可以在filter下做ThreadLocal对象set 和 remove 操作!
另外一个必须要提的点是:
ThreadLocal在线程池环境下的使用。
比如tomcat 提供的web http请求,一般都有线程池对请求做处理。
这种情况下要注意,并非每次web请求时候程序运行的ThreadLocal都是唯一的,ThreadLocal的生命周期不等于一次Request的生命周期,ThreadLocal与线程对象紧密绑定的,由于Tomcat使用了线程池,线程是可能存在复用情况,这时的ThreadLocal 的使用要谨慎使用。
web请求下 的ThreadLocal 使用要保证:请求进来的时候set,请求回去的时候remove。只有这样才能保证请求内的ThreadLocal 是唯一的。 这个特性在深刻的提醒我们:一次http请求和tomcat启动处理业务的线程并非一一对应的,而是通过一个线程池进行调度。
错误的使用案例:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/cd5533d788416a7bc2d665e7c6782adc.png)
@Controller
public class ThreadLocalController {
private static final ThreadLocal<Integer> id = new ThreadLocal<Integer>();
@ResponseBody
@RequestMapping("/threadLocalTest")
public Map<String, Object> threadLocalTest() {
Integer myId = id.get();
if (myId == null) {
id.set(1);
} else {
id.set(id.get() + 1);
}
System.out.println(id.get());
Map<String, Object> retMap = new LinkedHashMap<String, Object>();
retMap.put("id", id.get());
return retMap;
}
}
以上代码运行的时候会发现,命令行打印的id 是不确定的,这时因为tomcat本身对请求做线程池缓存业务处理线程导致的。
正确的使用案例:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/cd5533d788416a7bc2d665e7c6782adc.png)
@Controller
public class ThreadLocalController {
private static final ThreadLocal<Integer> id = new ThreadLocal<Integer>();
@ResponseBody
@RequestMapping("/threadLocalTest")
public Map<String, Object> threadLocalTest() {
Integer myId = id.get();
if (myId == null) {
id.set(1);
} else {
id.set(id.get() + 1);
}
System.out.println(id.get());
Map<String, Object> retMap = new LinkedHashMap<String, Object>();
retMap.put("id", id.get());
id.remove();
return retMap;
}
}
以上代码每次输出的都是1,注意id.remove() 方法的调用,在每次请求结束的时候remove对象。
更多的情况下,做为系统级别的,可以在filter下做ThreadLocal对象set 和 remove 操作!
相关文章推荐
- js手机界面调用安卓app
- 继承
- Linux 0.12内核与现代内核在内存管理上的区别
- rails中的正则表达式的相关错误提示
- [置顶] 转自百度百科——eclips中的快捷键的总结
- UE如何改变点击上传图片的弹出框的大小...
- Volley框架的学习总结(1)
- 关于xcode6升xcode7之后多window时,程序的状态栏管理问题
- [leetcode]ZigZag Conversion
- PL/SQL Developer如何连接64位的Oracle图解(转载)
- 在 Linux 中怎样将 MySQL 迁移到 MariaDB 上
- 关于EXC_BAD_ACCESS,以及解决办法
- 如何提取并输出使用forecast函数的预测值,ARIMA model in R
- android绘制花边view-WaveLineView
- [渗透测试] 渗透测试板块TIPs
- 《Linux Shell》笔记之dos2unix
- C语言联合体
- android studio 报错,google后无果
- PROPAGATION_REQUIRED
- BZOJ 1195 [HNOI2006]最短母串 状压DP