Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于TransmittableThreadLocal使用:只需要使用TransmittableThreadLocal就可以跨线程池传递?是不是不需要进行线程的修饰? #138

Closed
yinjihuan opened this issue May 7, 2019 · 8 comments
Assignees
Labels
❓question Further information is requested

Comments

@yinjihuan
Copy link

yinjihuan commented May 7, 2019

我目前测试下来,发现只需要使用TransmittableThreadLocal就可以跨线程池传递,疑问是到底要不要进行线程的修饰?

或者说,是不是可以不用配合下面的使用三种方式,直接使用TransmittableThreadLocal就可以了


TransmittableThreadLocal有3种使用方式:

  1. 修饰RunnableCallable
  2. 修饰线程池
  3. 使用Java Agent来修饰JDK线程池实现类
@yinjihuan
Copy link
Author

yinjihuan commented May 7, 2019

在我的测试Case中,用ThreadLocal 获取不到上下文的值,用TransmittableThreadLocal就可以。

@oldratlee oldratlee self-assigned this May 8, 2019
@oldratlee oldratlee added the ❓question Further information is requested label May 8, 2019
@oldratlee
Copy link
Member

oldratlee commented May 8, 2019

TransmittableThreadLocal有的3种使用方式都是可以完成跨线程池传递的。

可以认为后一种是前一种的对用户使用的简化。第3种『修饰线程或者线程池』的效果是『可以做到应用代码 无侵入』。


是不是可以不用配合下面的三种方式,直接使用TransmittableThreadLocal就可以了

不行的。

直接使用TransmittableThreadLocal就可以跨线程池传递了,想请教下修饰线程或者线程池的作用是什么?我测下来,不修饰也是可以的

你的测试Case不全、不典型。

『测试Case不全、不典型』的一个可能验证到的方法 是: @yinjihuan
在你的测试Case里,TransmittableThreadLocal换成ThreadLocal / InheritableThreadLocal,是不是 也是通过的。 😄

@oldratlee
Copy link
Member

oldratlee commented May 8, 2019

用threadLocal是获取不到值的,用TransmittableThreadLocal就可以

方便给一个极简的可运行复现问题的Demo仓库吗,这样可以实际看看你写的测试Case? :) @yinjihuan

@yinjihuan
Copy link
Author

链接: https://pan.baidu.com/s/1vh8ncJHcrHCmsiXK5dv7Ow 提取码: mpp4 复制这段内容后打开百度网盘手机App,操作更方便哦

@yinjihuan
Copy link
Author

yinjihuan commented May 8, 2019

传到网盘了
启动项目,访问 http://localhost:8311/test?id=1 ,可以看到控制台有如下输出:

http-nio-8311-exec-2:controller.test:1
SimpleAsyncTaskExecutor-1:service.test:null

第一行是Controller输出的,用的是tomcat的线程
第二行是Service输出的,用的是异步线程池的线程
使用ThreadLocal进行值传递是获取不到的

将RpcContent中ThreadLocal改成TransmittableThreadLocal后再次测试,值可以获取到,并没有对线程进行修饰

@oldratlee
Copy link
Member

oldratlee commented May 8, 2019

👍 OK @yinjihuan

初步的原因解释

你的Demo里,每次的异步任务@Async public void test()的线程都是 新线程(通过每个任务的线程名都是不同的,可以确认)。即 只要是InheritableThreadLocal就可以完成传递。
如果异步执行是线程池的方式(线程复用)就会传递出错了。

像这样Demo中,每次新线程 来异步执行的方式,在线上大流量并发的生产环境中往往是 不可接受的

运行出来的任务线程名的示例如下,各不相同:

......
SimpleAsyncTaskExecutor-124
SimpleAsyncTaskExecutor-126
SimpleAsyncTaskExecutor-125
SimpleAsyncTaskExecutor-127
SimpleAsyncTaskExecutor-128
......

推荐 梳理一下TransmittableThreadLocal的系统流程、查看代码实现。 @yinjihuan

可以看看 Issue『小伙伴同学们写的 TTL使用场景 与 设计实现解析的文章(写得都很好! )❤️ #123

这样我就不用通过这样Case-By-Case的具体场景分析来说明为什么其它的做法会有问题了 😄
理解了原理和流程,有些问题的原因 就不需要通过测试这样方式来确定,而是直接通过 分析/推理 给出。

PS

链接: https://pan.baidu.com/s/1vh8ncJHcrHCmsiXK5dv7Ow 提取码: mpp4 复制这段内容后打开百度网盘手机App,操作更方便哦

在GitHub上,推荐 @yinjihuan

  • Fork这个transmittable-thread-local,补一个单元测试,以极简的可运行复现问题
  • 或者,直接走一个GitHub仓库的代码Demo工程 :)

@yinjihuan
Copy link
Author

我再详细测试下

@yinjihuan
Copy link
Author

yinjihuan commented May 9, 2019

没问题了,之前我测过的。

『小伙伴同学们写的 TTL使用场景 与 设计实现解析的文章』里面有2篇文章还是我自己写的,哈哈。
只是最近我稍微试了一下,没仔细测,发现不修饰也可以获取值,我以为新版本改进了。

@oldratlee oldratlee changed the title TransmittableThreadLocal使用问题 关于TransmittableThreadLocal使用 May 9, 2019
@oldratlee oldratlee changed the title 关于TransmittableThreadLocal使用 关于TransmittableThreadLocal使用:只需要使用TransmittableThreadLocal就可以跨线程池传递,是不是不需要进行线程的修饰? Nov 10, 2019
@oldratlee oldratlee changed the title 关于TransmittableThreadLocal使用:只需要使用TransmittableThreadLocal就可以跨线程池传递,是不是不需要进行线程的修饰? 关于TransmittableThreadLocal使用:只需要使用TransmittableThreadLocal就可以跨线程池传递?是不是不需要进行线程的修饰? Nov 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants