ThreadLocal源码探析

闲谈ThreadLocal

前面在我的GitHub仓库 V-LoggingTool 中有简单的使用过ThreadLocal , 主要用在了切面类中 , 功能上需要取到前置增强拦截到的用户信息暂存 , 执行到后置增强时从该ThreadLocal中取出用户信息并使用 。
今天咱们就唠唠ThreadLocal的相关知识 , 了解一下它的数据结构、用法、原理等 。咱们层层深入...
 
看了网上不少关于ThreadLocal的讲解 , 源码比较简单但是对于Thread、ThreadLocal、ThreadLocalMap的关系讲的有点晦涩 , 尤其是那张亘古不变的ThreadLocal的内部结构图 , 额...我真的看了很久才明白是怎么回事 。
ThreadLocal工具类
ThreadLocal是一个本地线程副本变量工具类 , 主要用于将私有线程和该线程存放的副本对象做一个映射 , 各个线程之间的变量互不干扰 。
官方说的还是比较明白了 , 提炼关键字工具类 , 在我看来ThreadLocal就是提供给每个线程操作变量的工具类 , 做到了线程之间的变量隔离目的
内部结构图
ThreadLocal源码探析

文章插图
 
接下来就是看图说话:
  • 每个Thread线程内部都有一个ThreadLocalMap 。
  • Map里面存储线程本地对象ThreadLocal(key)和线程的变量副本(value) 。
  • Thread内部的Map是由ThreadLocal维护 , ThreadLocal负责向map获取和设置线程的变量值 。
  • 一个Thread可以有多个ThreadLocal 。
每个线程都有其独有的Map结构 , 而Map中存有的是ThreadLocal为Key变量副本为Vaule的键值对 , 以此达到变量隔离的目的 。
平时是怎么使用ThreadLocal的?
package threadlocal;/** * @Auther: Xianglei * @Company: JAVA编程之道 * @Date: 2020/7/2 21:44 * @Version 1.0 */public class main {    private static ThreadLocal<String> sThreadLocal = new ThreadLocal<>();    public static void main(String args[]) {        sThreadLocal.set("这是在主线程中");        System.out.println("线程名字:" + Thread.currentThread().getName() + "---" + sThreadLocal.get());        //线程a        new Thread(new Runnable() {            @Override            public void run() {                sThreadLocal.set("这是在线程a中");                System.out.println("线程名字:" + Thread.currentThread().getName() + "---" + sThreadLocal.get());            }        }, "线程a").start();        //线程b        new Thread(new Runnable() {            @Override            public void run() {                sThreadLocal.set("这是在线程b中");                System.out.println("线程名字:" + Thread.currentThread().getName() + "---" + sThreadLocal.get());            }        }, "线程b").start();        //线程c          new Thread(() -> {            sThreadLocal.set("这是在线程c中");            System.out.println("线程名字:" + Thread.currentThread().getName() + "---" + sThreadLocal.get());        }, "线程c").start();    }}


推荐阅读