这个类提供本地线程变量。不同于一般的变量,这些变量在他们各自的线程里通过 get、set 访问一个它自己的变量,这是一个独立初始化的变量副本。在一个类中,ThreadLocal 实例一般是 private static 的,期望和一个线程关联状态(如 userId,transactionId 等)。简单地说,就是此类提供了线程的本地变量,线程修改本地变量不互相影响。
举个例子,下面的类给每个线程生成一个唯一的标识。一个线程 id 在第一次调用 ThreadId.get() 被赋值,并且在后续的调用上保持不变。
|
|
只要线程还存活并且 ThreadLocal 实例可访问,那么每个线程持有一个确定的引用指向本地的变量副本,当线程消失,它的本地变量副本将会被GC(除非还被其他对象引用)。
使用案例
|
|
源码分析
ThreadLocal 的数据结构:实线表示强引用,虚线表示弱引用 每个 Thread 维护一个ThreadLocalMap 映射 table,映射 table 的 key 是 ThreadLocal 实例,value 就是线程存独立的变量副本的地方。 为什么这么设计,而不是由 ThreadLocal 来维护一个以 Thread 为 key 的映射呢?原因如下:
- 减小 Entry 数组大小:ThreadLocal 数量多,还是 Thread 的数量多,显而易见,使用 ThreadLocal 来当 key 可以减少 Entry 数量
- 减小内存占用:当 Thread 消亡,对 Thread 实例不在引用,则 GC 后就会清除相关数据
- 先看字段含义
|
|
- 主要方法:
|
|
核心方法 get() 相关内容:
|
|
其中的 getMap(Thread t):
|
|
Thread 类中的代码:这里可以看到是 Thread 持有 ThreadLocal.ThreadLocalMap 引用
|
|
其中的 map.getEntry(this):
|
|
核心方法 set() 相关内容:
|
|