ThreadLocal
ThreadLocal<T>
可以认为是一个绑定到当前Thread
的标签。
可以将一个value
绑定到这个标签,形成一个Entry
存储到由Thread
维护的ThreadLocalMap
中。
ThreadLocalMap
ThreadLocalMap是ThreadLocal
的一个静态内部类,其实就是一个重新实现过的HashMap
,相对于HashMap
有如下特点:
- 定义一个继承自
WeakReferener<ThreadLocal<?>>
的静态内部类Entry
:
1 | static class Entry extends WeakReference<ThreadLocal<?>> { |
作用类似于HashMap
中的Entry
,只不过这个Entry
的key是自身的外部类ThreadLocal<T>
,value
则是ThreadLocal<T>
的泛型参数。这就是前面为什么说ThreadLocal<T>
其实是一个标签。
这个做法有一个非常精妙的地方,前面提到过ThreadLocalMap
并不是由ThreadLocal
维护的,而是由每一个Thread
维护自己的ThreadLocalMap
。也就是说当线程退出之后,对应的ThreadLocalMap
将会被回收,里面存储的所有Entry
也会被回收。
但需要注意的是,在这个设计中Entry
的ThreadLocal<T>
是弱引用,而value
是强引用,意味着当ThreadLocal<T>
的引用被销毁后,Entry
对value
的引用依然存在,所以如果需要回收ThreadLocal
对应的数据,则需要手动将value
一并回收,否则会发生内存泄漏
- 与
HashMap
不同,ThreadLocalMap
在处理哈希冲突的时候使用的是开放地址法
,当位置被占用的时候会直接去找下一个位置,利用空间换取时间,效率要高于HashMap
ThreadLocal如何与Thread绑定
先来看ThreadLocal中的get
和set
方法:
1 | public T get() { |
从源码中可以看出,ThreadLocal在操作之前都会通过Thread
类获取当前线程,从而保证下一步获取到的ThreadLocalMap
永远是在当前线程中维护的,从而将自己对应的数据
绑定到线程。