ThreadLocal的终极问题,拜求解答

下面是几篇不错的文章,论坛还有很多,可以搜一下,讨论的相当火热!
http://blog.csdn.net/happyzhm5/archive/2007/08/09/1734047.aspx
http://www.iteye.com/topic/103804?page=1

我的总结:
这个问题的起源在研究Hibernate和公司框架时发现的Session release问题,看源码和资料,发现用ThreadLocal比较多。

June 总结:
1. 原理(可以这么想,但内部src不是这样)
通过例子可以看出:ThreadLocal的原理是用一个synchronized Map来存储当前线程相关的变量。这样在每一个线程用到obj时,都要取new一个Object。这其实也是很消耗内存的
2. 与new Object的区别
好处1 :区别在于同一个线程用到的都是同一个实例,也就是说本线程在不同的时间,不同的地方(函数等)用到的都是同一个obj,这样的好处是:减少了new 出来的实例obj数量!
好处2 :同一个线程共享一个实例变量,而线程间的实例变量却不同!
这个好处可以用在Dao操作时,同一个线程得到同一个Session,这样方便于Transaction的整体操作!
好处3 :既然用到obj时不用取new,这样也就少了分配空间、初始化、等开销,这本身相当于一个缓存,只不过这个缓存不是全局的,而是线程局部的!
坏处 :同一个线程共享同一个同一个obj可能会造成混淆!即在线程内,又得注意同步:即当前obj的状态!这个坏处一般破坏不大,因为在同一个线程内,一般不会再开线程,同时,在一个Thread内,是顺序执行,我们非常熟悉,一般不会出错,忘了顺序走过来的值现在的状态(即同一个线程不开子线程 = = 单线程,那么状态可以知道)。多线程的根本问题在于多个线程执行时间、顺序是随即的异步的,状态是不可预测或随机的。
3. synchronized与ThreadLocal
首先说资源共享与竞争,这其实一样,都是多个Thread随机的访问某个变量值,如果不加设置,可能会导致读脏数据、写冲突、等问题。
(1) 需要共享,这个值 不可以设置 不可以改变 那么可以用一个final static解决
(2) 需要共享,这个值可以设置可以改变,那么共享的话会出错!
A 如果需要同步该数据,那么需要用synchronized
B 如果不需要同步数据,那么可以把这个变量变成线程内变量
根据上面分析,synchronized是为了解决同步问题,而同步根本用不着ThreadLocal。
ThreadLocal解决的是同一个线程内的资源共享问题,而synchronized 解决的是多个线程间的资源共享问题,两个问题没有可比性。
4. ThreadLocal根本的用处
从上面ThreadLocal与new Object、与synchronized 的比较,可以知道,ThreadLocal最根本的用处在于:线程内共享数据,即保证当前线程内取到的都是统一对象的引用。
好处:在同一个线程内,完全不相关的两个段代码、函数之间如何共享一个变量呢?通过ThreadLocal可以做到
而且这两段代码之间不用显式的传递参数,降低了耦合。
在java_doc里的描述很到位!如下:
该类提供了线程局部变量。这些变量不同于它们的普通对应物,因为访问一个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的私有静态字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。
5. 遗留问题:如何释放资源
ThreadLocal中,其它线程无法访问本线程的局部变量!其实也不需要访问,如果需要,那就需要用别的方法!
那么,当前线程结束后,如何才能释放掉现在占用的资源呢?ThreadLocal并没有留下接口,亦不知道其内如是如何做的,但释放资源是个大问题,尤其在保存有重量级资源时,如连接数据库,Socket连接等。

终极问题?如何释放资源
ThreadLocal中,其它线程无法访问本线程的局部变量!其实也不需要访问,如果需要,那就需要用别的方法!
那么,当前线程结束后,如何才能释放掉现在占用的资源呢?ThreadLocal并没有留下接口,亦不知道其内如是如何做的,但释放资源是个大问题,尤其在保存有重量级资源时,如连接数据库,Socket连接等。

Java中ThreadLocal没有留下接口destroy,很是遗憾!
如何释放资源,等待ing ...

------------------------------------------------------------
2009-04-08更新
写这篇文章好久,提问也但没有人来看,不过本人这几天研究发现一个不错的方法,理论可以,还有待实践。
ThreadLocal没有留下释放资源的接口是有原因的:谁知道什么时候线程终止?也就是说,线程的生命周期是不可预期的!而Thread本身没有留下destroy接口,那么ThreadLocal就没办法了!
解决的方法就是用java1.2引入的弱引用:PhantomReference,重写父类ReferenceQueue,促发释放资源的动作!

没时间了,特简写,有需要的朋友可以交流!

你可能感兴趣的:(Java_about)