ThreadLocal
摘自:https://www.jianshu.com/p/3c5d7f09dfbd
ThreadLocal 的简单使用方法:
static final ThreadLocal<T> sThreadLocal = new ThreadLocal<T>(); sThreadLocal.set(); sThreadLocal.get();
ThreadLocal 是一个线程内部的存储类,可以在指定线程内存储数据,数据存储后,只有指定线程可以得到存储的数据。它提供的线程内存储变量的能力,这些变量不同之处在于每一个线程读取的变量是对应互相独立的。通过 get 和 set 方法就可以得到当前线程对应的值。
做个不恰当的比喻:从表面上看 ThreadLocal 相当于维护了一个 map,key 就是当前的线程,value 就是需要存储的对象。这个比喻不恰当在于,实际上是 ThreadLocal 的静态内部类 ThreadLocalMap 为每个 Thread 都维护了一个数组 table,ThreadLocal 确定了一个数组的下标,而这个下标就是 value 存储的对应位置。即:每个线程持有一个 ThreadLocalMap 对象,每个新的线程 Thread 都会实例化一个 ThreadLocalMap 并赋值给成员变量 threadLocals。
//在某一线程声明了ABC三种类型的ThreadLocal ThreadLocal<A> sThreadLocalA = new ThreadLocal<A>(); ThreadLocal<B> sThreadLocalB = new ThreadLocal<B>(); ThreadLocal<C> sThreadLocalC = new ThreadLocal<C>();
对于一个 Thread 来说,只持有一个 ThreadLocalMap,所以 ABC 对应同一个 ThreadLocalMap 对象。为了管理 ABC,于是将他们存储在一个数组的不同位置,而这个数组就是上面提到的 Entry 型的数据 table。ABC 在 table 中的位置的确定,为了能正常的访问对应值,
总结:
1、对于某一 ThreadLocal 来讲,他的索引值 i 是确定的,在不同线程之间访问的是不同的 table 数组,即使位置相同都是 table[i],但是线程之间的 table 是独立的。
2、对于同一线程的不同 ThreadLocal 来讲,这些 ThreadLocal 实例共享一个 table 数组,然后每个 ThreadLocal 实例在 table 中的索引 i 是不同的。
Spring使用ThreadLocal解决线程安全问题
使用到 ThreadLocal 的:
1)分页的 PageHelper
2)Spring Security里面的 SecurityContextHolder.getContext()
存 context 就是 SecurityContextHolderStrategy,这个类使用了 ThreadLocal
3)Spring 使用 ThreadLocal 来设计 TransactionSynchronizationManager 类,
实现了事务管理与数据访问服务服务的解耦,同时也保证了多线程环境下 connection 的线程安全问题