ThreadLocal 源码学习及应用

    源码分析

    ThreadLocal 类实际上是以空间换时间的一种同步机制。相对于Synchronize方法的对时间的同步分配,ThreadLocal是将每个线程对应的副本值保存在一个Map中。ThreadLocal的基本机制就是如此。

    通过阅读源码发现,其实这个Map(即ThreadLocalMap)是在每个Thread中的,每个Thread的Map用以存储这个Thread的所有的ThreadLocal,故ThreadLocalMap<ThreadLocal,V>。因为ThreadLocal使用时是以static存在的,这个类共享一个ThreadLocal的变量。之前一直以为ThreadLocalMap是在ThreadLocal中。

    另外,ThreadLocalMap的Entry是一个WeakReference的,这样保证了每个Map中存放的对象在内存紧张时GC后会得以回收。

    应用1

    ThreadLocal类被广泛使用在Spring中,例如JDBC的Connection和Hibernate的Session都是绑定在ThreadLocal实现的上下文中。一般来讲,资源(即connection和session)的生命周期是是事务绑定在一起的(connection-per-transaction/session-per-transaction),每个有事务的Service方法中由AOP来管理资源,得益于Servlet应用中每个请求都是一个线程的模型这种实现十分合理而方便,具体的步骤如下:

  1. 若当前线程执行到了一个需要进行事务控制的方法(如某个service的方法),通过AOP拦截,spring会在方法执行前申请一个数据库连接或者一个hibernate session.
  2. 成功获得资源后,开启一个事务。
  3. 将资源也就是数据库连接或是hibernate session的实例存放于当前线程的ThreadLocal里(也就是进行所谓的线程绑定)
  4. 在方法执行过程中,任何需要获得数据库连接或是hibernate session进行数据访问的地方都会从当前线程的ThreadLocal里取出同一个数据库连接或是hibernate session的实例进行操作(这个动作由Spring提供的各种Template类实现)。
  5. 方法执行结束,同样通过AOP拦截,spring取出绑定到当前线程上的事务(对于hibernate来说就是取出绑定在当前线程上一个SessionHolder实例,它保存着当前的session与transaction实例),执行提交。
  6. 事务提交之后,释放资源,清空当前线程上绑定的所有对象!
  7. 如果该线程之后有新的事务发起,一切会重新开始,Spring会使用新的数据库连接或是hibernate session实例,开始新的事务,两个事务之间没有任何关系。

    应用2

    以下应用转载自http://my.oschina.net/u/580483/blog/113654

    由于DateFormat对象是线程非安全的,而每次应用都new一个的代价不小,所以可以将一个DateFormat绑定到一个Thread中。

你可能感兴趣的:(spring,threadLocal,transaction)