InheritableThreadLocal的使用和最简单易懂源码分析

ThreadLocal的基本使用和源码

关于ThreadLocal的知识点需要看另外一篇博客:
ThreadLocal从简单使用及源码

InheritableThreadLocal基本使用

在了解完ThreadLocal后,我们来看下面例子:
在这里插入图片描述
会发现ThreadLocal的一个弊端:父子线程无法共享数据
那么我们对例子进行一下改造:使用InheritableThreadLocal完美解决这个问题
在这里插入图片描述

源码分析:

这里先试着停下思考:
(1)它是怎么让子线程拿到了父线程设置的参数?
(2)它放在哪里?又怎么取出来?
必须有这两点疑问去看,才会更好理解

1:怎么放?

这里要非常注意区分父线程创建子线程,哪个是父,哪个是子
第一步先直截了当告诉大家它这个参数值存放在哪里:
在这里插入图片描述
这里可以简单理解为放的位置不一样,但是我们都知道ThreadLocal的Value,都是存放在对应Thread里面的,所以真正重要的,还是要看Thread初始化创建部分怎么设置这两个值

再从线程的初始化说起:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

⚠️注意这里初始化默认给的true很重要,这一步在接下来会进行判断

在这里插入图片描述
再往下面一点,有另外一段逻辑:
在这里插入图片描述
判断:如果当前父线程的inheritableThreadLocals被设值了,那么就通过createInheritedMap方法,返回一个ThreadLocalMap存放到当前正在创建的子线程类中,为什么要这样做呢?因为这样就可以把正在创建子线程的父线程的inheritableThreadLocals值,赋值一份给到了正在创建的子线程的inheritableThreadLocals,这段绕,需要分清楚谁是当前创建人和谁是被创建中
继续看createInheritedMap方法:
在这里插入图片描述
发现该方法创建了一个新的ThreadLocalMap然后返回,源码说返回的这个map,就是跟父线程相关联的,

怎么取?

这个就比较简单了,inheritableThreadLocals重写了一个方法:
在这里插入图片描述

使其返回的不是t.threadLocal,而是t.inheritableThreadLocals,而这个getMap方法,恰恰就是获取对应线程的ThreadLocalMap方法,进一步从map中get出Value,然后return,至此全剧终
在这里插入图片描述
在这里插入图片描述

配合线程池使用的坑⚠️

根据上面的源码分析,我们不难得出结论:必须是初始化的子线程,才能继承父线程的inheritableThreadLocals变量,那么如果是线程池,因为是复用线程的原因,没有进行init,所以自然也就没办法进行重新赋值,会导致从子线程get出来的参数与父线程往InheritableThreadLocal塞进去的参数不一致问题

猜你喜欢

转载自blog.csdn.net/whiteBearClimb/article/details/123063900