ThreadLocal , TransmittableThreadLocal

196 阅读1分钟

ThreadLocal

场景:它的应用就是比如当前用户特有的一些属性,不能跟其他线程,用户共用。

TransmittableThreadLocal

场景:就是父子线程或者线程池中共用变量。


class ThreadLocalTest {

    public static ExecutorService TTLExecutor = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(5));
    //定义另外一个线程池循环执行,模拟业务场景下多Http请求调用的情况
    public static ExecutorService loopExecutor = Executors.newFixedThreadPool(5);
    AtomicInteger i = new AtomicInteger(0);
    //TTL的ThreadLocal
    public static ThreadLocal tl = new TransmittableThreadLocal<>(); //这里采用TTL的实现

    public static void main(String[] args) {
//        System.out.println(Thread.currentThread().getName());
        SysDeptServiceImplTest.test2();
//        SysDeptServiceImplTest.test3();
//        SysDeptServiceImplTest.test4();

//        ExecutorService loopExecutor = Executors.newFixedThreadPool(5);
//        for (int i = 0; i < 10; i++) {
//            loopExecutor.execute(() -> {
//                System.out.println("父线程" + Thread.currentThread().getName());
//                SysDeptServiceImplTest.test5();
//            });
//        }
    }


    /**
     * ThreadLocal 值共享:当前线程
     */
    public static void test1() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1));
        ThreadLocal local = new ThreadLocal();
        local.set(1);

        System.out.println("打印1:" + local.get());
        executor.execute(() -> {
            System.out.println("打印2:" + local.get());
        });

    }

    /**
     * InheritableThreadLocal 值共享:当前线程和子线程,但是线程池的不行(看test2_1)
     */
    public static void test2() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1));
        ThreadLocal local = new InheritableThreadLocal();
        local.set(1);
        System.out.println("打印1:" + local.get());
        executor.execute(() -> {
            local.set(2);
            System.out.println("打印2:" + local.get());
        });
        System.out.println("打印3:" + local.get());
    }

    /**
     * InheritableThreadLocal 值共享:当前线程和子线程,但是线程池的不行。
     */
    public static void test2_1() {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1));

        ThreadLocal local = new InheritableThreadLocal();
        local.set(1);


        executor.execute(() -> {
            System.out.println("打印1:" + local.get());
        });

        local.set(2);

        System.out.println("打印2:" + local.get());

        executor.execute(() -> {
            local.set(3);
            System.out.println("打印3:" + local.get());
        });
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("打印4:" + local.get());
    }

    /**
     * TransmittableThreadLocal 值共享:当前线程,子线程,线程池
     */
    public static void test3() {
        AtomicInteger i = new AtomicInteger(0);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
            while (true) {
                if (i.get() < 10) {
                    tl.set(i.getAndAdd(1));
                }
                TTLExecutor.execute(() -> {
                    System.out.println(String.format("1子线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
                });
            }
        }).start();
    }

    public static void test4() {
        AtomicInteger i = new AtomicInteger(0);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
            while (true) {
                if (i.get() < 10) {
                    tl.set("A");
                }
                TTLExecutor.execute(() -> {
                    System.out.println(String.format("2子线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
                });
            }
        }).start();
    }

    public static void test5() {
        AtomicInteger i = new AtomicInteger(0);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
            while (true) {
                if (i.get() < 10) {
                    tl.set(i.getAndAdd(1));
                    TTLExecutor.execute(() -> {
                        System.out.println(String.format("1子线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));
                    });
                }

            }
        }).start();
    }

    public static void test6() {

    }
}