了解Java多线程编程的同学,想必对ThreadLocal并不陌生,看过ThreadLocal源码的同学对其设计一定会赞不绝口,下面我们一起走进ThreadLocal的源码(Java 8),看看具体是如何设计的。
1 ThreadLocal 是什么?
ThreadLocal是指线程的本地变量,我们可以通过ThreadLocal去设计只有线程内部才可以访问的变量,该变量是与其他线程所隔离的。
2 ThreadLocal 可以干什么?
ThreadLocal最大的特点就是线程隔离,其他线程无法获取,当前线程ThreadLocal存放的数据,然后就是在ThreadLocal中存放的信息,无论其程序的调用链路有多深,只要是同一个线程,无需参数传递,可以直接获取。
3 ThreadLocal 典型应用
一个比较典型的应用场景就是,MyBatis分页插件中的应用,需要分页的接口,需要先将分页信息放入ThreadLocal中,需要用的时候直接通过ThreadLocal获取,这样就不需要每个接口都传入分页信息,然后再传给分页插件。
Spring的声明式事物中,也应用了ThreadLocal来存储事物信息,因为我们只有使用同一个数据库连接,设置事物才会生效,Spring的事物管理器在获取到数据库连接后就会将其与ThreadLocal绑定,事物完成后解除绑定。
4 ThreadLocal 源码解析
ThreadLocal 的源码是相对容易看懂的,我们以ThreadLocal的set方法为入口,开始看其原理
- 首先set方法会先获取当前线程 t
- 通过当前线程 t 获取当前线程的ThreadLocalMap对象
- 判断ThreadLocalMap是否为空
- 不为空时 为map设置值,key为当前的ThreadLocal对象,value为传入的参数
- 为空时 调用ThreadLocalMap构造函数初始化对象
public class ThreadLocal<T> {
......
// ThreadLocal设置值
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// 获取当前线程的ThreadLocalMap对象
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
// 当前线程ThreadLocalMap对象为空时,调用ThreadLocalMap构造函数初始化对象
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
// ThreadLocalMap为ThreadLocal的静态内部类,为Thread的属性
static class ThreadLocalMap {
......
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entr