1. 程式人生 > >ThreadLocal & InheritableThreadLocal 使用的一些坑

ThreadLocal & InheritableThreadLocal 使用的一些坑

  1. 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);
         }
     } }
  1. 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