threadlocal跨线程传递解决方案(上)

1.在面试的过程中。经常会遇到面试官提到threadlocal的问题,很多情况下:

面试官最爱问的是:

threadlocal是做什么用的,用在哪些场景当中?

这个很多同学基本上也能提到:

ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景。简单易懂的就是。每个线程有自己的数据副本,当线程结束后可以独立回收。

通常使用场景:

比如spring mvc收到请求。拦截器将用户id等数据放到threadlocal当中。在当前线程就可以直接拿到数据

具体例子:

有些同学会说出开源项目中有些地方会用到:

比如这种,比如mysql读写分离。主写读从过程中,类似于shardingsphere的中间件。就通过threadlocal来实现某一次读请求路由到主库。通过threadlocal设置标识即可

2.那么面试官继续问:

如果我启动另外一个线程。那么在主线程设置的threadlocal值能被子线程拿到吗?

如果拿不到,怎么去解决这个问题。有的同学一定会想这种场景比较少。顶多就是面试官找茬罢了

其实不然。这种场景非常普遍。举一个例子:

现在微服务基本上属于各个大厂小厂的标配。有一个问题。全链路如何来做监控。如果用过spring cloud的同学一定会说。zipkin,有的可能也会说cat,pinpoint,skywalking等等,

暂且不讨论这些全链路组件的优劣。在全链路组件落地的过程中,threadlocal是一个相当关键的步骤。拿zipkin的实现来说:

核心的数据传递都通过threadlocal来实现

那么回到我刚才的问题。threadlocal跨线程是否能够传递呢?那么我们做一个实验:

相关代码。我们在父线程设置了一个threadlocal。另外启动一个线程去获取

运行结果:

结论:拿不到数据。获取的是个null

那我们应该怎么去解决这个问题:

在java8中提供了一个这个类(InheritableThreadLocal):

从字面意思来看:可以实现父线程到子线程的共享,那么我们实验一下

将实现换成了InheritableThreadLocal

看一下效果 (果然解决了问题):

InheritableThreadLocal原理:

看一下目录结构:


复写了父类3个方法

当主线程中对该变量进行set操作的时候,和ThreadLocal一样会初始化一个ThreadLocalMap对实际的变量值进行存储,以ThreadLocal为key,值为value,如果有多个ThreadLocal变量也都是存储在这个Map中。该Map使用的是HashMap的原理进行数据的存储,但是和ThreadLocal有一点差别,因为其覆写了createMap的方法。

在Thread类当中,可以看出Thread类维护了两个成员变量,ThreadLocal以及InheritableThreadLocal,数据类型都是ThreadLocalMap.这也就解释了为什么这个变量是线程私有的。但是如果要知道为什么父子线程的变量传递,那就继续看一下源码。当我们在主线程中开一个新的子线程的时候,开始会new一个新的Thread

在thread构造函数中,new一个thread方法

可以看到,最后会调用ThreadLocal的createInheritedMap方法,而该方法会新建一个ThreadLocalMap,看一下构造函数的内容:


parentMap就是父线程的ThreadLocalMap,这个构造函数的意思大概就是将父线程的ThreadLocalMap复制到自己的ThreadLocalMap里面来,这样我们就可以使用InheritableThreadLocal访问到父线程中的变量了

但是这个就能解决问题了吗。并不是~

下个小结我会继续讲解InheritableThreadLocal在多线程调用过程中还存在哪些坑。如何解决

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 原理 产生线程安全问题的根源在于多线程之间的数据共享。如果没有数据共享,就没有多线程并发安全问题。ThreadLo...
    Java耕耘者阅读 334评论 0赞 0
  • 我想ThreadLocal这东西,大家或多或少都了解过一点,我在接触ThreadLocal的时候,觉得这东西很神奇...
    CoderBear阅读 689评论 0赞 2
  • 一、简介 并发编程中,当访问共享数据时,通常需要使用同步技术。但如果数据不发布(逸出)到线程以外,仅仅在单线程中被...
    邱simple阅读 3,580评论 3赞 12
  • 生命中感恩遇到慈悲大爱智慧的格西老师,让我通过种子法则的学习放大格局,有意的做出慷慨的行为,去施善帮助能帮到的人。...
    张蓉萍阅读 165评论 0赞 1
  • 日精进打卡 【知~学习】 学习活法一书的大概内容介绍及评论 【经典名句 要带着一颗比降生时稍稍善良、稍稍美丽的心...
    J0hn先生阅读 71评论 0赞 0

友情链接更多精彩内容