锁定老帖子 主题:关于ThreadLocal模式的体会
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-17
threadlocal内部貌似是使用了Thread.currentThread().getName()来当做key,在jdk1.5中是一种效率比较低的做法,据说在6.0速度有提升,但是实际中用途也不是很广泛,只有在权限系统或者保存数据库Connection时才会用到。
|
|
返回顶楼 | |
发表时间:2010-03-17
是呀,我们把threadlocal放在session中 |
|
返回顶楼 | |
发表时间:2010-03-17
61234865 写道 我有一个地方不太明白,就是我们用SSH的时候,如果你用threadlocal来存变量,你第二次请求的时候怎么能保证获取到的线程就是和先前的线程一样的?如果不一样,那数据岂不是就丢失了?
不知道你看清楚上面写的文章没有。ThreadLocal只能充当当前线程的Context,线程结束,当前线程ThreadLocal中存放的变量也被销毁了。 但是这里必须注意的是:我们通常所用的tomcat中所使用的是线程池技术,即我们在web开发中,每个请求所使用的线程不一定都被销毁了(有可能被放回线程池中),即存放在其中的变量也没有被销毁。在这种前提我们必须注意一下几点: 1. 我们却无法保证二次请求之间使用的是同一个线程,所以二次请求之间ThreadLocal不能共享 2. 即使能保证,那也会出现问题,因为所有ThreadLocalMap中存放的key都是一样,如果你取得的线程之前已经被另外的线程使用过,这个时候,你从ThreadLocalMap取得的变量有可能不是你原来存放的变量,会出现一些未知的错误,所以如果我们在使用ThreadLocal的时候,如果是在线程池的环境下,那我们每次使用完ThreadLocal后,记得把里面的变量清空。 所以对应在web开发中,我们必须认为ThreadLocal的作用域跟request对象一样,ThreadLocal中存放的变量对应一次请求到结束,第二次我们再使用ThreadLocal时,再重新往里面存放变量。 |
|
返回顶楼 | |
发表时间:2010-03-17
抛出异常的爱 写道 61234865 写道 我有一个地方不太明白,就是我们用SSH的时候,如果你用threadlocal来存变量,你第二次请求的时候怎么能保证获取到的线程就是和先前的线程一样的?如果不一样,那数据岂不是就丢失了?
同次请求的不丢就很了不起了. 如果同此请求也会丢失,那ThreadLocal不是成鸡肋了? 难道tomcat处理的请求的时候,不能够保证同一个请求只使用同一个线程处理? |
|
返回顶楼 | |
发表时间:2010-03-17
抛出异常的爱 写道 不知道有哪个项目是这么用的.
可以解决很多参数问题. 为什么没人说webwork? |
|
返回顶楼 | |
发表时间:2010-03-17
61234865 写道 我有一个地方不太明白,就是我们用SSH的时候,如果你用threadlocal来存变量,你第二次请求的时候怎么能保证获取到的线程就是和先前的线程一样的?如果不一样,那数据岂不是就丢失了?
可以用拦截器,每次有请求都重新赋值,比如从session中取出放到ThreadLoacl中 用他的好处就是不用传参数 |
|
返回顶楼 | |
发表时间:2010-03-17
我记得过去测试过一次,在web中使用threadlocal保存变量,结果在线程消失后,变量值并没有自动清除,貌似request线程下,需要自己手动清除才可以,然后我们用threadlocal更多的情况下是为了保存dao,使其单例才可以完成方法的事务的完整性传播特性,用户对象这种个人认为没有必要threadlocal来保存。
|
|
返回顶楼 | |
发表时间:2010-03-17
可以这么做,不过个人理解这是对ThreadLocal的误用。
ThreadLocal充当当前线程的Context,同时也可以理解为ThreadLocal变量的作用域属于Thread。 业务方法的参数的生命周期可能是瞬态的,无端的放入ThreadLocal中会延长这些对象的生命周期,注意回收。 好的,我们会及时清理,如果真要这样做,还需要再写代码,不知有何优点。 同时这些业务方法没有了参数的描述会变得晦涩,还被强制的要求在同一线程的原理下工作。抽象依赖实现,不可取。
PS: “ThreadLocal不是用来解决对象共享访问问题的”------如果Java没有了多线程,大家还需要ThreadLocal么。 ThreadLocal 和 request的作用域完全是不同的。
|
|
返回顶楼 | |
发表时间:2010-03-18
最后修改:2010-03-18
allengao 写道 我记得过去测试过一次,在web中使用threadlocal保存变量,结果在线程消失后,变量值并没有自动清除,貌似request线程下,需要自己手动清除才可以,然后我们用threadlocal更多的情况下是为了保存dao,使其单例才可以完成方法的事务的完整性传播特性,用户对象这种个人认为没有必要threadlocal来保存。
因为一般的servlet,JSP容器,都使用的线程池技术,所以当一个请求处理完成直到向客户端发送响应结束后,调度这个请求处理的线程没有被销毁而被放回线程池,所以threadlocal保存的变量也并没有被销毁,必须我们手动清除。 |
|
返回顶楼 | |
发表时间:2010-03-18
vivide 写道
可以这么做,不过个人理解这是对ThreadLocal的误用。
ThreadLocal充当当前线程的Context,同时也可以理解为ThreadLocal变量的作用域属于Thread。 业务方法的参数的生命周期可能是瞬态的,无端的放入ThreadLocal中会延长这些对象的生命周期,注意回收。 好的,我们会及时清理,如果真要这样做,还需要再写代码,不知有何优点。 同时这些业务方法没有了参数的描述会变得晦涩,还被强制的要求在同一线程的原理下工作。抽象依赖实现,不可取。
PS: “ThreadLocal不是用来解决对象共享访问问题的”------如果Java没有了多线程,大家还需要ThreadLocal么。 ThreadLocal 和 request的作用域完全是不同的。
我也非常肯定你的观点:ThreadLocal 和request的作用域肯定是不相同的,ThreadLocal 中存放的变量的生命周期只存活于当前线程,而request的作用域在于一个请求处理结束。在tomcat的线程池环境下,基本上都是request处理完成后,线程都被回放到线程池,即request作用域结束,ThreadLocal 中ThreadLocalMap存放的变量也并没有被销毁。我说的是可以认为ThreadLocal 和 request的作用域是相同的 ,因为即使线程没被回收,我们也无非再找回之前处理过的线程,即使找回那个线程,那个线程也许被另外的request使用过,里面存放的是其他的参数,所以我在这里假设ThreadLocal 和 request的作用域是相同的是为了让大家明白,ThreadLocal 在实际使用过程中最好且也只有用于一次请求处理。
|
|
返回顶楼 | |