首都高赛车免安装正式中文版
6.7G · 2025-10-10
原文来自于:zha-ge.cn/java/84
身为老 Java 程序员,ThreadLocal 早就烂熟于心,可有次聊起多线程变量传递,居然被面试官出了道“你用过 InheritableThreadLocal 吗?”的骚操作。当场脑门一紧:啥?ThreadLocal 还有“亲儿子版”?其实我刚入行业的时候,老觉得:ThreadLocal 不就是让每个线程自个儿玩自个的吗?结果这几年业务越来越离谱,各种异步线程池、请求串联,突然发现真有点东西——
于是,这个“山寨 ThreadLocal”到底是个啥?用起来和老本尊真的一样吗?不啰嗦,咱聊点程序员的心里话。
有回我在写个用户上下文,登录用户信息放 ThreadLocal,原以为安全得很:
threadLocal.set(userInfo); // 请求线程里塞进去
// ……业务处理……
结果写了个异步队列,子线程要调这个信息。嗯,结果好嘛,直接空指针打脸。原来线程变量还真没“遗传”到新开的线程里?(难道咱 ThreadLocal 这么绝情吗?)
当时的内心 OS 可以用一句话总结:
后来 Google 一下,发现江湖上居然流传着 InheritableThreadLocal 这么个“带血缘”的东西!
说干就干,把 ThreadLocal 换成 InheritableThreadLocal,心想“变量终于能随儿子线程流淌了”。
private static final InheritableThreadLocal<User> userCtx =
new InheritableThreadLocal<>();
// 父线程塞进去
userCtx.set(user);
// 子线程再读
User u = userCtx.get();
new Thread()
真·新线程跑,嗬,还真能拿到。又查查官方文档,才发现 InheritableThreadLocal 只有在线程刚创建、start 的时候,才会把父线程的变量复制一份给子线程(其实是 clone,不是引用)。 线程池里的线程是池化的,起都起好了,不会每次复制。
你瞅瞅,这玩意简直比前任还迷惑:
核心点其实很简单:
特性 | ThreadLocal | InheritableThreadLocal |
---|---|---|
变量范围 | 当前线程 | 当前线程 + 新建子线程(仅new Thread) |
线程池行为 | 线程独立 | 线程独立,老线程不自动复制 |
数据可传递性 | 不可跨线程 | 只在 new 出来、刚启动的子线程里会变“遗传” |
要注意:
写给下一位壮士的几点建议:
写完这些随手抬头,才发现,被各路“ThreadLocal 儿孙”虐了一圈,只有自己最靠谱。切记: 上下文传播,Java 能帮的那点事,图省事你就输了。
好啦,今天的“ThreadLocal DNA 鉴定”就聊到这。放下代码,喝口水,远望天花板,继续在 Bug 的路上奋勇前行吧。