InheritableThreadLocal存在的问题
InheritableThreadLocal提供了子线程继承父线程的ThreadLocal的能力,对于手动创建的线程,可以直接获取父线程中ThreadLocal的内容,彼此之间互不干扰
public class InheriThreadLocalDemo {
private static final InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
threadLocal.set("main");
for (int i = 1; i <= 3; i++) {
final int finalI = i;
new Thread(() -> {
threadLocal.set(threadLocal.get()+ "->task" + finalI);
System.out.println(threadLocal.get());
}).start();
}
TimeUnit.SECONDS.sleep(1);
}
}
main->task1
main->task3
main->task2
而如果是线程池的场景,再使用InheritableThreadLocal就会出现问题;
主要是因为线程池中的线程使用完不会销毁,下一次还会继续使用
public class ThreadLocalDemo {
private static final InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
threadLocal.set("main");
for (int i = 1; i <= 3; i++) {
final int finalI = i;
executorService.submit(() -> {
threadLocal.set(String.format("%s->%s%d", threadLocal.get(), "task", finalI));
System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
});
}
TimeUnit.SECONDS.sleep(2);
executorService.shutdown();
}
}
pool-1-thread-2: main->task2
pool-1-thread-1: main->task1
pool-1-thread-1: main->task1->task3
比如上面的例子,我原本是希望每个子线程获取的ThreadLocal值是main;
但是观察pool-1-thread-1这个线程,第二次复用时,获取的ThreadLocal值是main->task1,即保留了上一次set的值
使用TransmittableThreadLocal
- 装饰Runnable
public class TransThreadLocalDemo {
private static final TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
threadLocal.set("main");
for (int i = 1; i <= 3; i++) {
final int finalI = i;
executorService.submit(TtlRunnable.get(() -> { // 装饰Runnable
threadLocal.set(String.format("%s->%s%d", threadLocal.get(), "task", finalI));
System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
}));
}
TimeUnit.SECONDS.sleep(1);
executorService.shutdown();
}
}
- 装饰ExecutorService
public class TransThreadLocalDemo2 {
private static final TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(executorService); // 装饰ExecutorService
threadLocal.set("main");
for (int i = 1; i <= 3; i++) {
final int finalI = i;
ttlExecutorService.submit(() -> {
threadLocal.set(String.format("%s->%s%d", threadLocal.get(), "task", finalI));
System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
});
}
TimeUnit.SECONDS.sleep(1);
ttlExecutorService.shutdown();
}
}
结果符合预期,即使线程复用,也不会互相干扰
pool-1-thread-2: main->task2
pool-1-thread-1: main->task1
pool-1-thread-1: main->task3
3658

被折叠的 条评论
为什么被折叠?



