日期:2014-05-20  浏览次数:20799 次

ThreadLocal 与 给每个线程实例传递一个新的变量,这两种做法的区别
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。
------------
我还是没明白用Threadlocal有啥好处啊.我完全可以给每个线程实例传递一个新的变量啊。这样不就可以不用threadlocal了么?
它是每个线程一个副本,互不影响。那跟我刚才的做法有区别吗?
threadlocal 貌似跟同步无关了哦。不存在资源争用了,还同步啥呢。

------解决方案--------------------
主要是用来传递消息的,这边用set那边用get获取,根本不需要知道变量名是多少,只要知道是threadlocal就能获取到
------解决方案--------------------
怎么传递呢?估计相对麻烦多。
它是内建的,现成的,拿来就用,使用方便。
------解决方案--------------------
Threadlocal一般用在:

1.缓存实例化开销较大的实例
经常将java.sql.Connection的实例放到Threadlocal中。

2.缓存非线程安全的实例
多线程环境下,非线程安全对象。
如SimpleDateFormat,不能在多线程下正常工作,又不想每次都实例化,就可以放在Threadlocal中(只有该线程才能用到它)。

3.处理并发处理冲突问题
当在Spring环境下用到编程式事务时,通常会获取Spring Context中的TransactionManager来管理事务。
如果直接这样做的话,一定会死锁!!!
(我有遇到这样的问题,短时间内提交20次,正常情况下会有20条记录,但结果往往少于20,而且可以看到后台有线程死锁)。

解决的方案就是将TransactionManager放入到Threadlocal中,之前的问题就没有了!
被放入到Threadlocal中的都是同一个TransactionManager实例!

可以看看下面这个资料,对并发做了详细的介绍。
Java Concurrency

------解决方案--------------------
很多时候线程的创建不是由你控制,而是由框架控制,无法传递变量。比如web服务器中的线程。

这时候,除了使用ThreadLocal,还有其他更好的办法吗?
------解决方案--------------------
我的认为:ThreadLocal是为了分层,传递变量无疑是越层的操作,会让两个层之间的耦合性变差。就像事务控制一般在service层上,如果你想控制Dao层呢?Dao层依旧获取它所需的变量,比如Connection,不必考虑线程神马的问题,在Service层中用ThreadLocal控制Dao层,这样就完成了“越层控制”的目的。