ThreadLocal 在web环境下使用的边界问题

ThreadLocal 相关分析,请查看[url]http://wangxinchun.iteye.com/blog/1884228[/url]
另外一个必须要提的点是:
ThreadLocal在线程池环境下的使用。
比如tomcat 提供的web http请求,一般都有线程池对请求做处理。

这种情况下要注意,并非每次web请求时候程序运行的ThreadLocal都是唯一的,ThreadLocal的生命周期不等于一次Request的生命周期,ThreadLocal与线程对象紧密绑定的,由于Tomcat使用了线程池,线程是可能存在复用情况,这时的ThreadLocal 的使用要谨慎使用。

web请求下 的ThreadLocal 使用要保证:[b]请求进来的时候set,请求回去的时候remove。只有这样才能保证请求内的ThreadLocal 是唯一的。[/b] 这个特性在深刻的提醒我们:一次http请求和tomcat启动处理业务的线程并非一一对应的,而是通过一个线程池进行调度。
[b]错误的使用案例:[/b]

@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本身对请求做线程池缓存业务处理线程导致的。

正确的使用案例:

@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对象。

[b]更多的情况下,做为系统级别的,可以在filter下做ThreadLocal对象set 和 remove 操作![/b]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值