`

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

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

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

web请求下 的ThreadLocal  使用要保证:请求进来的时候set,请求回去的时候remove。只有这样才能保证请求内的ThreadLocal  是唯一的。 这个特性在深刻的提醒我们:一次http请求和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());
		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对象。

更多的情况下,做为系统级别的,可以在filter下做ThreadLocal对象set 和 remove 操作!
1
0
分享到:
评论
6 楼 王新春 2014-07-30  
root123 写道
王新春 写道
thc1987 写道
我现在的做法是做个过滤器,每次请求都更新一下

恩,可以根据实际的情况,对web请求型的做成filter 不错。但是在定时任务或者线程池中,只要注意 set remove 成对出现即可。

每次任务开始时,都进行设置。这样的方案可行吗?

当然也可以。
5 楼 root123 2014-07-30  
王新春 写道
thc1987 写道
我现在的做法是做个过滤器,每次请求都更新一下

恩,可以根据实际的情况,对web请求型的做成filter 不错。但是在定时任务或者线程池中,只要注意 set remove 成对出现即可。

每次任务开始时,都进行设置。这样的方案可行吗?
4 楼 王新春 2014-06-13  
thc1987 写道
我现在的做法是做个过滤器,每次请求都更新一下

恩,可以根据实际的情况,对web请求型的做成filter 不错。但是在定时任务或者线程池中,只要注意 set remove 成对出现即可。
3 楼 thc1987 2014-06-13  
我现在的做法是做个过滤器,每次请求都更新一下
2 楼 王新春 2014-06-12  
kidding87 写道
感觉你把Threadlocal用错场景了,而且需要是的request.get/setAttribute

我仅仅是做ThreadLocal 的功能和使用场景的演示的
1 楼 kidding87 2014-06-12  
感觉你把Threadlocal用错场景了,而且需要是的request.get/setAttribute

相关推荐

Global site tag (gtag.js) - Google Analytics