ThreadLocal怎么用?用不好

hibernate里对session 的处理就是用的ThreadLocal.

本人在项目中有些想法也想用这个东西,但不知道怎么用合适

比如一个业务对象的pool,在一个操作中被多次用到,当然不想每次刷新最新数据,最好是本线程中刷新一次就好。初看是个用ThreadLocal地方。

但这个东东不好用,

首先只能放一个东东进去,取出来的时候又要转型。多个东西怎么放?
直接放一个map进去么?中途被误覆盖了怎么办,很难查。

还有界面是swing,有人说,swing调后台都是一个线程,真的?
也就是说用户所有的操作都是在一个线程里?

还有ThreadLocal在RMI里表现如何呢?

你可以看看JForum的源码。

具体的我还没有完全搞明白 :(

使用ThreadLocal又回到线程编程原始时代,Hibernate这样的基础框架迫于无奈可以用用,应用系统我个人认为不能用。

jsp/servlet本来就是让我们回避多线程编程的环境,现在倒好,被这些框架打着先进设计理念的旗帜又倒退了。唉。

Web容器中有三个周期request/Httpsession/application
其中request是客户端发出的一个请求,这个request的载体就是一个线程,实际等同于一个线程的生命周期。

Request是封装在线程上面一个抽象概念。

而ThreadLocal则相当于多个线程的一个共享全局变量存储地,它里面保存的是和每个线程相关的状态。所以threadLocal是为线程服务的,和线程处于一个底层位置。

正因为Spring/Hibernate这些框架对于状态处理短处,所以才只能透过Web容器的request等状态封装,直接到底层操作与线程同一层次的threadLocal。

当一个线程或request结束时,threadlocal中的状态就没有了,所以threadLocal基本类似request.setAttribute作用,threadLocal中的对象状态的生命周期等同于request.

状态对象:数据库的替代者:
http://www.jdon.com/artichect/state.htm

使用ThreadLocal可以大量减少参数的传递,可以使代码简洁,但是一定要明白,一个线程会绑定多个自己定义的局部对象,ThreadLocal是抽象在线程上的对象创建工厂,目前的Tomcat5使用了线程池,一个线程处理一个request,这样ThreadLocal对象可以抽象的绑定在request生命周期,不会存在线程危机,而且线程池也平衡了这些ThreadLocal对象的消耗,但是tomcat 6使用nio技术,一个线程可能会处理多个request,提高处理访问能力的情况下,ThreadLocal的使用将会出现问题,对象不再服务于一个request,所以ThreadLocal的长期使用需要注意!

但是tomcat 6使用nio技术,一个线程可能会处理多个request,提高处理访问能力的情况下,ThreadLocal的使用将会出现问题,对象不再服务于一个request,所以ThreadLocal的长期使用需要注意!


对不起,这句话是错误的,nio技术的目的是解决java进行socket网络连接不具备异步性做出的并发优化处理,也就是服务端和客户端数据传递可以使用nio技术,让一个线程处理多个数据读写连接,在tomcat 6下,对于我们是透明的,它在我们的两头,而容器将数据调入我们发布的程序进行请求处理时,还是一个request对应一个线程的!所以ThreadLocal的使用是没有问题的!

to luyao_bai:
你把ThreadLocal当做是一个以当前线程为key的Hashtable去理解就可以了。
[该贴被slangmgh于2007年09月05日 13:46修改过]

晕,我自己研究了半天才搞明白了一点ThreadLocal的问题,原来这里早就已经有人搞定了!
我现在做一个项目,需要在业务层得到用户登录的UserBean,以进行数据与操作权限控制,但又不想从Action中每次都调用业务层的setUser方法来做,这样总觉得耦合合紧了,代码写起来也麻烦,不优雅。
一直找不到好办法,后来看了下acegi的实现,才想了一个方法:
做一个RequestServletListener,然后在每次request时,从session中取得UserBean,置到ThreadLocal中,这样在业务层就可以直接取用了。
就是有一点忐忑不安,1、这个Listener与request是不是在一个线程中?现在看起来是的,以后?;2、HttpRequest和业务层会不会总在一个线程中?现在测试起来是在,以后WEB容器有了新版本时,如果不在,那不是全完蛋了?

>HttpRequest和业务层会不会总在一个线程中
万变不离其宗,JavaEE本质就是线程。