首页 > 其他分享 >使用 transmittable-thread-local 组件解决 ThreadLocal 父子线程数据传递问题

使用 transmittable-thread-local 组件解决 ThreadLocal 父子线程数据传递问题

时间:2023-08-14 11:15:05浏览次数:38  
标签:transmittable thread 租户 ThreadLocal 线程 executorService local id

在某个项目中,需要使用mybatis-plus多租户功能以便数据隔离,前端将租户id传到后端,后端通过拦截器将该租户id设置到ThreadLocal以便后续使用,代码大体上如下所示:

ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();
threadLocal.set(1);
Java  

我在Controller层使用线程池取了租户id,代码大体上如下所示:

ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(()->{
	//获取租户id
});
Java  

这时候出问题了,出现了有时候取得到有时候取不到租户id的现象,但是经过若干次重试之后就能稳定获取到租户id;再次测试则发现如果前端传了其它的租户id,后端取得还是上一次获取到的租户id,这到底是为啥呢?

问题分析:首先,这里使用了InheritableThreadLocal为的就是实现父子线程传值,传了值也能取到,但是也不总是能取到,若干次之后就总是能取到了。看到这种现象,我们正常人的第一反应就是怀疑这里有缓存,每次使用的时候没有,使用完了就缓存起来,由于线程池在执行任务的时候并非总是使用同一条线程,当线程池中的核心线程全都缓存完了,再请求就稳定不报错了,然而有缓存的原因所以就算这时候外部请求换了一个租户id,线程池中的线程仍然使用的是老的租户id,这也是缓存最直接的体现。。。。。。这里纯属基于现象的个人猜测,并没有什么实锤,看官们谨慎驾驶,小心翻车。

那怎么解决该问题呢?

该问题产生的原因是InheritableThreadLocal的bug,至于什么bug,我也不清楚(笑),但是有解决方案,解决方案就是使用阿里的transmittable-thread-local 组件,github地址如下:https://github.com/alibaba/transmittable-thread-local 使用起来也非常简单

首先,引入maven依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.12.0</version>
</dependency>
XML  

1. 改变ThreadLocal的创建方式

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

// =====================================================

// 在父线程中设置
context.set("value-set-in-parent");

// =====================================================

// 在子线程中可以读取,值是"value-set-in-parent"
String value = context.get();
Java  

2.改变线程池创建方式

ExecutorService executorService = ...
// 额外的处理,生成修饰了的对象executorService
executorService = TtlExecutors.getTtlExecutorService(executorService);

Java  

也就是说除了正常创建线程池之外,还要对该线程池做一个代理。

就这么简单,搞完之后父子线程传数据就一切正常了。

ps. 个人觉得这里称呼"父子线程"并不妥当,因为线程池是系统启动之后就已经创建好了的,算了,钻牛角尖太没劲了。

标签:transmittable,thread,租户,ThreadLocal,线程,executorService,local,id
From: https://www.cnblogs.com/tiancai/p/17628084.html

相关文章

  • 谈谈对TransmittableThreadLocal的理解
    前言最近遇到一个问题,公司内部有一个公共的SSO包,用来获取HTTP请求中的登录态,代码中会直接用这个包的方法获取用户登录信息,在代码任意位置直接用SSOUtil.getUser()获取用户信息,在我们一个下载的业务代码中,用到了线程池开启子任务处理请求,结果发现子任务中拿到的用户信息和HTTP请......
  • 国产MCU-CW32F030开发学习- 移植rtthread-nano
    国产MCU-CW32F030开发学习--移植rtthread-nano硬件平台CW32_48F大学计划板CW32_IOT_EVA物联网开发评估套件RT-ThreadNanoRT-ThreadNano是一个极简版的硬实时内核,它是由C语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的RTOS。其内存资源......
  • RT-Thead学习-GD32移植(基于RT-Thread Nano源码)
    1前言当前关于RT的移植教程有很多,纯复制大佬们的很迷糊,参考官方手册和一些经验贴,完成了基于Nano源码的移植,最简单的移植教程就是基于keil的和这一种。参考资料1.野火资料(https://doc.embedfire.com/rtos/rtthread/zh/latest/application/porting_to_stm32.html)2.微信公众号(物联网......
  • 线程池使用InheritableThreadLocal踩坑总结
    一、缘起某天测试环境更新后,有小伙伴反应页面会随机性的发生请求参数为空的情况(request.getParamter为空),但是前端的参数是传了的,而且不能稳定重现,需要在页面上经过一番操作之后才会发生,而当问题重现之后,之前那些可用的页面就变得不可用了,然后就会在可用和不可用之间交替........
  • 异步线程变量传递必知必会---InheritableThreadLocal及底层原理分析
    InheritableThreadLocal简介笑傲菌:多线程热知识(一):ThreadLocal简介及底层原理3赞同·0评论文章上一篇文章我们聊到了ThreadLocal的作用机理,但是在文章的末尾,我提到了一个问题,ThreadLocal无法实现异步线程变量的传递。什么意思呢?以下面的代码为例子:@SneakyThrowspublicBo......
  • new Thread().start(); - 多线程练习
     用Java创建一个线程是这样的:Threadthread=newThread();要启动Java线程,您将调用其start()方法,如下所示:   thread.start();此示例未指定要执行的线程的任何代码。线程启动后会立即再次停止。所以要往线程里写入代码。Threadthread=newThread(){@Override......
  • c#关于终止thread 学习经典
    C#多线程学习笔记之(abort与join配合使用)转载:************   原文中的评论,有便于理解的内容*************************C#多线程学习笔记之(abort与join配合使用)  今天刚开始学多线程,尽管以前用过一点点,但是只是照着网上代码抄,没有真正理解,现在回过头来想研究研究,......
  • Android View绘制原理 - RenderThread
    前面的文章介绍了HardwareRendere在初始化的时候,涉及到了一个组件RenderThread并简要的分析了一下,这篇文章将继续深入的分析一下这个RenderThread,介绍一下它的几个重要特性和功能1ThreadRenderThread首先是继承自ThreadBase,是一个真实的线程。frameworks/base/libs/hwui/rendert......
  • .NET Core多线程 (1) Thread与Task
    去年换工作时系统复习了一下.NETCore多线程相关专题,学习了一线码农老哥的《.NET5多线程编程实战》课程,我将复习的知识进行了总结形成本专题。同时也特别推荐有兴趣的读者去学习一线码农老哥的《.NET5多线程编程》课程。本篇,我们来复习一下Thread与Task的相关知识点,预计阅读时......
  • 三个实例演示 Java Thread Dump 日志分析
    jstackDump日志文件中的线程状态dump文件里,值得关注的线程状态有:死锁,Deadlock(重点关注) 执行中,Runnable  等待资源,Waitingoncondition(重点关注) Waitingonmonitorentry(重点关注)暂停,Suspended对象等待中,Object.wait()或TIMED_WAITING阻塞,Blocked(重点关注)......