- ThreadLocal在与线程池结合使用时可能会出现数据复用
线程池把线程提交到队列,当被调用的时候如果存在空闲线程就回直接复用线程,仅仅是调用了用户提交线程的run方法。所以当ThreadLocal参数使用完,记得调用remove方法。
public class B {
static final ThreadLocal<String> threadParam = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
//固定池内只有存活3个线程
ExecutorService execService = Executors.newFixedThreadPool(3);
//死循环几次才能看出效果
while (true) {
Thread t = new Thread(()->{
threadParam.set("abc");
System.out.println("t1:" + threadParam.get());
//如果不调用remove,将引发问题 // threadParam.remove();
});
execService.execute(t);
TimeUnit.SECONDS.sleep(1);
Thread t2 = new Thread(()-> {
System.out.println("t2:" + threadParam.get());
});
execService.execute(t2);
}
} }
- InheritableThreadLocal 和 线程池结合使用时会出现共享父线程的InhertiableThreadLocal
public static void main(String[] args) throws InterruptedException {
//固定池内只有存活3个线程
ExecutorService execService = Executors.newFixedThreadPool(3);
//死循环几次才能看出效果
while (true) {
//线程1,里面有两个子线程
Thread t = new Thread(()->{
threadParam.set("abc");
System.out.println("t1:" + threadParam.get());
Thread t2 = new Thread(()->{
System.out.println("t2:" + threadParam.get());
// threadParam.remove();
});
execService.execute(t2);
Thread t3 = new Thread(()->{
System.out.println("t3:" + threadParam.get());
// threadParam.remove();
});
execService.execute(t3);
Thread t4 = new Thread(()->{
System.out.println("t4:" + threadParam.get());
// threadParam.remove();
});
execService.execute(t4);
});
execService.execute(t);
TimeUnit.SECONDS.sleep(1);
//线程4,线程1同级
Thread t5 = new Thread(()-> {
threadParam.set("CBA");
System.out.println("t5:" + threadParam.get());
});
execService.execute(t5);
}
}
Another case see the below link:
https://blog.csdn.net/Sunfj0821/article/details/81349775