ThreadLocal

发布时间 2023-07-12 16:51:50作者: archaique

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 内部类定义