ThreadLocal的吐槽与

第一次看到ThreadLocal是jfinal-weixin的项目中,多公众号的实现方法,才知道这个“好东西”,实在太方便了,可以打通单一线程内任意地方的数据交流,传递一些当前会话的“全局变量”,或者业务端唯一性标识的信息,有了解过或者看过jfinal-weixin源码或者知道shiro的都应该能体会这玩意有多好用多方便。颇有刚学c语言的时候,全局变量打天下,goto语句随意跳转的快感。

就这么一个“好东西”,如果没用好还是会整出不少严重的bug,线程内set了之后线程结束前“必须一定务必”要remove,否则线程回到线程池之后,内容会溢出到其它session。这个问题导致的bug一直让我头疼,只能严格遵守往TL里set东西之后要尽快remove掉,或者用try{}finally{}来确保无论如何都完成这个步骤。但,总有人为疏忽的时候,或者未知的流程下触发这个溢出问题。

网上看了很多没有找到特别好的办法解决这个问题,只了解到FastThreadLocal就专门解决这个痛点,并且还达到更高的性能和安全性,自动释放,然而必须结合Netty的FastThread线程池来实现,否则在普通线程下会退化为SlowThreadLocal,即jdk原本的实现。这个线程池分配好像不是可以随便改的,目前我们新开发的项目用的是Jboot框架,undertow运行,根据我的了解线程池是在undertow这层管理的。

那么,各位大佬有在用到ThreadLocal开发的吗,有遇到我类似的痛点问题吗,你们是怎么优雅的处理的。或者,没有使用TL的大佬有没有使用类似特性的玩意呢。又或者是完全舍弃这种特性,用别的思路或者设计来达到相同效果的。

欢迎一起讨论,一起学习,进步!

评论区

zeroabc

2022-06-20 21:41

@山东小木 分享的TransmittableThreadLocal

JFinal

2022-06-20 22:25

不同线程明确知道需要共享 ThreadLocal 中的对象时,下不需要 remove(),例如 JDK 中的 java.math.BigDecimal 中的 threadLocalStringBuilderHelper

共享变量类的缓冲区也可以不必 remove,例如 enjoy 中的 WriterBuffer,多个线程在不同的时间段内可以共享,而 ThreadLocal 可以保障同一个变量在每个时刻只被一个线程使用

zeroabc

2022-06-20 23:09

https://github.com/alibaba/transmittable-thread-local/issues/123

zeroabc

2022-06-20 23:15

@JFinal 使用场景主要就是线程内的“全局变量”。我是放在一个工具类使用的,private static final FastThreadLocal> threadMap = new FastThreadLocal>();然后有还有setThreadMap(String key, Object value);removeThreadMap();removeThreadMap(String key);get方法;

zeroabc

2022-06-20 23:16

https://github.com/alibaba/transmittable-thread-local/issues/128

zeroabc

2022-06-21 10:54

@JFinal 詹总,刚好想到之前项目有个情况,因为TL多数时候用法是try{serTL();拦截器invoke();}finally{removerTL();}有一次就是前端render的时候用到TL的东西,但是拦截器invoke()的后面其实是发生在response写之前的,这时候TL清空,render已经拿不到想要的东西,当然这个场景可以用别的处理方法,小问题。那么詹总有没有考虑过after拦截器,或者现有的拦截器加个afterResponse()回调呢,应该还是有应用场景的。

杜福忠

2022-06-21 12:57

@zeroabc 我用的Handler处理TL,存放租户唯一标识

zeroabc

2022-06-21 13:41

@杜福忠 杜佬,上个码来看看ヽ( ̄▽ ̄)ノ

杜福忠

2022-06-21 14:44

@zeroabc 这个有啥放的,在handle里面 next.handle 之前放serTL(),之后removerTL()就可以了,ActionHandler里面 render 执行时就可以拿到值了。Invocation不行,因为它在render之前invoke运行完毕了。所以你上面代码换成handle最合适了
https://jfinal.com/doc/2-7

zeroabc

2022-06-21 15:00

@杜福忠 噢,确实,感谢提醒