ThreadLocal
类主要解决的就是让每个线程绑定自己的值,可以存储每个线程的私有数据。
如果你创建了一个ThreadLocal
变量,那么访问这个变量的每个线程都会有这个变量的本地副本。
Thread 类
public class Thread implements Runnable { //...... //与此线程有关的ThreadLocal值。由ThreadLocal类维护 ThreadLocal.ThreadLocalMap threadLocals = null; //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; //...... }
ThreadLocal
类的set()
方法
public void set(T value) { //获取当前请求的线程 Thread t = Thread.currentThread(); //取出 Thread 类内部的 threadLocals 变量(哈希表结构) ThreadLocalMap map = getMap(t); if (map != null) // 将需要存储的值放入到这个哈希表中 map.set(this, value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
最终的变量是放在了当前线程的 ThreadLocalMap
中,并不是存在 ThreadLocal
上,ThreadLocal
可以理解为只是ThreadLocalMap
的封装,传递了变量值。 ThrealLocal
类中可以通过Thread.currentThread()
获取到当前线程对象后,直接通过getMap(Thread t)
可以访问到该线程的ThreadLocalMap
对象。
ThreadLocalMap 类的定义在 ThreadLocal 类中,是 ThreadLocal 类的一个内部类, key 是 ThreadLocal<T> 的一个对象,value 是这个 <T> 的实际值
Thread 线程类有一个字段,ThreadLocal.ThreadLocalMap threadLocals = null,是 ThreadLocal.ThreadLocalMap 类的一个实现对象,也就是每个线程对象都有一个 ThreadLocal 对象
ThreadLocal<T> 相当于一个维护所有线程 ThreadLocal.ThreadLocalMap threadLocals = null 这个属性,即所有线程 <T> 的取值 value 的一个工具类
下面用一个例子说明这一点
import dto.TreeNode; import java.util.Random; public class testThreadLocal implements Runnable{ private static final ThreadLocal<TreeNode> treeNodeThreadLocal = new ThreadLocal<>(); private static final ThreadLocal<Integer> integerThreadLocal = new ThreadLocal<>().withInitial(() -> 0); public static void main(String[] args) throws InterruptedException { testThreadLocal thisclass = new testThreadLocal(); for(int i=0 ; i<10; i++){ Thread t = new Thread(thisclass, ""+i); Thread.sleep(new Random().nextInt(1000)); t.start(); } } @Override public void run() { System.out.println("Thread Name= "+Thread.currentThread().getName()+" integerThreadLocal = "+ integerThreadLocal.get()); Integer curThreadInt = new Random().nextInt(1000); treeNodeThreadLocal.set(new TreeNode(curThreadInt, Thread.currentThread().getName())); integerThreadLocal.set(curThreadInt); System.out.println("Thread Name= "+Thread.currentThread().getName() +" integerThreadLocal = "+integerThreadLocal.get() +" treeNodeThreadLocal = "+treeNodeThreadLocal.get()); } }
输出结果如下
treeNodeThreadLocal 和 integerThreadLocal 这两个 ThreadLocal 类的对象与线程的关系如下所示
ThreadLocal. ThreadLocalMap 内部类定义