本文主要是介绍TransmittableThreadLocal (TTL),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
官方文档
问题描述
在日常的开发中,我们经常会通过多线程来提高业务执行效率,例如:
当前登录用户信息放在ThreadLocal内,然后service在处理业务逻辑时通过线程池来异步的处理,由于线程池内的线程与当前主线程不是同一个,因此获取不到主线程存放的用户信息
Runnable runnable = ()->{while(true){//处理用户数据-会从ThreadLoca内获取登录人信息System.out.println("当前ThreadLocal值为=>"+threadLocal.get());try {ThreadUtil.sleep(1000);} catch (Exception e) {throw new RuntimeException(e);}}
};Runnable runnable2 = ()->{//处理订单数据-会从ThreadLoca内获取登录人信息System.out.println("当前ThreadLocal值为=>"+threadLocal.get());
};
//异步处理用户数据
CompletableFuture.runAsync(runnable,executor);
//主线程操作
threadLocal.set("hello TTL");//异步处理订单数据
CompletableFuture.runAsync(runnable2,executor);
JDK为我们提供了 InheritableThreadLocal
,但是他只有在创建新线程时才会拷贝(一个新线程只拷贝一次),而线程池内的核心线程是不会销毁的,会处理多个任务,因此就无法获取到当前登录人信息(或者会获取其他人的登录信息)。
这种情况我们就可以使用Alibaba
为我们提供的 TransmittableThreadLocal
来解决这个问题。
TTL使用
TransmittableThreadLocal继承自InheritableThreadLocal,并扩展了多次拷贝主线程ThreadLocal的功能。
示例:
/**
*打印结果:修改为hello TTLpool-1-thread-1当前ThreadLocal值为=>0pool-1-thread-1当前ThreadLocal值为=>0pool-1-thread-1当前ThreadLocal值为=>0pool-1-thread-1当前ThreadLocal值为=>hello TTLpool-1-thread-1当前ThreadLocal值为=>hello TTLpool-1-thread-1当前ThreadLocal值为=>hello TTL
*/
public class TestTTL {//创建线程池static ExecutorService executor = new ThreadPoolExecutor(1,1,5,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),new ThreadPoolExecutor.CallerRunsPolicy());//使用TransmittableThreadLocalstatic TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();public static void main(String[] args){threadLocal.set("0");Runnable runnable = ()->{for(int i=0;i<3;i++){//处理用户数据System.out.println(Thread.currentThread().getName()+"当前ThreadLocal值为=>"+threadLocal.get());ThreadUtil.sleep(1000);}};//执行任务1 注意此处需要通过 TtlRunnable.get(runnable)改变runnable类CompletableFuture.runAsync(TtlRunnable.get(runnable), executor);//主线程 修改 ThreadLocalthreadLocal.set("hello TTL");System.out.println("修改为hello TTL");//执行任务2CompletableFuture.runAsync(TtlRunnable.get(runnable),executor);executor.shutdown();}
}
Agent方式无侵入实现
上面的代码中我们使用了 TransmittableThreadLocal,然后在提交Runnable任务时我们需要通过 TtlRunnable.get(runnable) 来修饰Runnable。但是如果我们项目中的代码已经写好了,如果要修改成本很大,此时就可以通过Agent挂载的方式来动态修改Runnable类
方法:启动时配置 javaagent
java -javaagent:C:\Users\gudian\Desktop\test\transmittable-thread-local-2.14.2.jar
-jar my.jar
这篇关于TransmittableThreadLocal (TTL)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!