日志数据如何完美适配多线程完成正常输出
在大麦项目的讲解中,提到了如何自定义线程池来传递 ThreadLocal 和日志 MDC 中的数据,而为了让大家更加掌握的更加全面以及如何对已存在的线程池进行适配,本章节将详细讲解刚才提到的问题是如何解决的
ThreadLocal多线程取值问题
先看第一个例子,主线程向 ThreadLocal 中设置值 test1,然后开启线程池,再从ThreadLocal中取
public class Test0 {
ThreadLocal<String> threadLocal = new ThreadLocal<>();
ExecutorService executors = Executors.newFixedThreadPool(10);
public void test1(){
threadLocal.set("test1");
System.out.println("主线程设置值 : " + threadLocal.get());
executors.submit(() -> {
System.out.println("线程池取值 : " + threadLocal.get());
});
}
public static void main(String[] args) {
Test0 test0 = new Test0();
test0.test1();
}
}
结果
主线程设置值 : test1
线程池取值 : null
结果是线程池当然取不到了,解决此问题最简单就是将 ThreadLocal 类型换成 TransmittableThreadLocal 类型
TransmittableThreadLocal多线程取值
public class Test1 {
TransmittableThreadLocal<String> ttl = new TransmittableThreadLocal<>();
ExecutorService executors = Executors.newFixedThreadPool(10);
public void test1(){
ttl.set("test1");
System.out.println("主线程设置值 : " + ttl.get());
executors.submit(TtlRunnable.get(() -> {
System.out.println("线程池取值 : " + ttl.get());
}));
}
public static void main(String[] args) {
Test1 test1 = new Test1();
test1.test1();
}
}
和第一个例子相比,把 ThreadLocal 类型换成 TransmittableThreadLocal 类型,并将线程池中的任务用 TtlRunnable.get 包装了一层
结果
主线程设置值 : test1
线程池取值 : test1
结果是没有问题的,平时项目也是这么用的,但是和日志结合起来就有问题了