zoukankan      html  css  js  c++  java
  • ThreadLocal >InheritableThreadLocal>TransmittableThreadLocal解决线程池中变量传值问题

    InheritableThreadLocal  ITL可以解决父线程传本地变量给子线程,但是无法解决线程池模式下正确传值。

    TransmittableThreadLocal TTL,在线程池模式下,也可以正确的将父线程的本地变量传给子线程

    TTL的用法:

    加入依赖:

        <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>transmittable-thread-local</artifactId>
                <version>2.13.0-Beta1</version>
            </dependency>
    1.线程池使用TtlExecutors.getTtlExecutorService封装:
    TtlExecutors.getTtlExecutorService(executorService);
    2.变量使用TransmittableThreadLocal
    TransmittableThreadLocal<String> transmittableThreadLocal=new TransmittableThreadLocal<>();

    上代码可以看到区别:

    1.工厂类:MyFactory.java
    
    public class MyFactory implements ThreadFactory {
        private String name;
        private AtomicLong count = new AtomicLong(0);
        public MyFactory(String name){
            this.name=name;
        }
    
        @Override
        public Thread newThread(Runnable r) {
            String a = count.getAndIncrement() + "";
            System.out.println("创建线程,名字:" + name+"_"+a);
            Thread thread = new Thread(r);
            thread.setName(name+"_"+a);
            thread.setDaemon(true);
            return thread;
        }
    }

    2.线程:
    ThreadOne.java
    public class ThreadOne  implements  Runnable{
    private CountDownLatch latch;
    private String name;
    ThreadOne(CountDownLatch l,String name){
    this.latch=l;
    this.name=name;
    };
    @Override
    public void run() {
    System.out.println("线程名字:"+name+" tl:"+TwoMain.threadLocalValue.get()+" ITL "+TwoMain.inheritableThreadLocalValue.get()
    +" TTL:"+TwoMain.transmittableThreadLocal.get());

    try {
    Thread.sleep(1000*1);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    latch.countDown();
    }
    }

    3.main函数
    public class TwoMain {
    public static ThreadLocal<String> threadLocalValue = new ThreadLocal<>();
    public static InheritableThreadLocal<String> inheritableThreadLocalValue = new InheritableThreadLocal<>();
    public static TransmittableThreadLocal<String> transmittableThreadLocal=new TransmittableThreadLocal<>();
    public static void main(String[] args) {
    ExecutorService executorService = new ThreadPoolExecutor(5, 10, 0, TimeUnit.SECONDS, new ArrayBlockingQueue(6), new MyFactory("线程池"));
    ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(executorService);
    CountDownLatch latch = new CountDownLatch(30);
    threadLocalValue.set("AAAAAA");
    inheritableThreadLocalValue.set("AAAAAA");
    transmittableThreadLocal.set("AAAAAA");
    for (int i = 0; i < 30; i++) {
    ThreadOne t = new ThreadOne(latch, i + "");
    try {
    ttlExecutorService.submit(t);
    } catch (Exception e) {
    // System.out.println(e.getMessage());
    latch.countDown();
    }
    }
    try {
    System.out.println("线程名字:"+Thread.currentThread().getName()+" threadlocal:"+threadLocalValue.get()+" inheritthreadLocal:"+inheritableThreadLocalValue.get());
    System.out.println("我先睡会儿!!");
    latch.await();
    System.out.println("我开始下一场");

    } catch (InterruptedException e) {
    e.printStackTrace();
    }

    System.out.println("我把TL/ITL/TTL值都设置成BBBBB");
    threadLocalValue.set("BBBBB");
    inheritableThreadLocalValue.set("BBBBB");
    transmittableThreadLocal.set("BBBBB");
    for (int i = 0; i < 30; i++) {
    ThreadOne t = new ThreadOne(latch, i + "B");
    try {
    ttlExecutorService.submit(t);
    } catch (Exception e) {
    // System.out.println(e.getMessage());
    latch.countDown();
    }
    }
    }
    }
    
    
    
    
    
    
    
    

    结果:

    创建线程,名字:线程池_0
    创建线程,名字:线程池_1
    创建线程,名字:线程池_2
    创建线程,名字:线程池_3
    线程名字:1 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:0 tl:null ITL AAAAAA TTL:AAAAAA
    创建线程,名字:线程池_4
    线程名字:2 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:3 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:4 tl:null ITL AAAAAA TTL:AAAAAA
    创建线程,名字:线程池_5
    创建线程,名字:线程池_6
    创建线程,名字:线程池_7
    创建线程,名字:线程池_8
    线程名字:11 tl:null ITL AAAAAA TTL:AAAAAA
    创建线程,名字:线程池_9
    线程名字:12 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:14 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:15 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:13 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:main threadlocal:AAAAAA inheritthreadLocal:AAAAAA
    我先睡会儿!!
    线程名字:6 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:5 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:7 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:9 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:8 tl:null ITL AAAAAA TTL:AAAAAA
    线程名字:10 tl:null ITL AAAAAA TTL:AAAAAA
    我开始下一场
    我把TL/ITL/TTL值都设置成BBBBB
    线程名字:0B tl:null ITL AAAAAA TTL:BBBBB
    线程名字:1B tl:null ITL AAAAAA TTL:BBBBB
    线程名字:3B tl:null ITL AAAAAA TTL:BBBBB
    线程名字:2B tl:null ITL AAAAAA TTL:BBBBB
    线程名字:4B tl:null ITL AAAAAA TTL:BBBBB
    创建线程,名字:线程池_10
    创建线程,名字:线程池_11
    线程名字:11B tl:null ITL BBBBB TTL:BBBBB
    创建线程,名字:线程池_12
    线程名字:12B tl:null ITL BBBBB TTL:BBBBB
    创建线程,名字:线程池_13
    创建线程,名字:线程池_14
    线程名字:14B tl:null ITL BBBBB TTL:BBBBB
    线程名字:13B tl:null ITL BBBBB TTL:BBBBB
    线程名字:15B tl:null ITL BBBBB TTL:BBBBB

    Process finished with exit code 0

    可以看到:

    threadlocal不会把值传给子线程

    当更改父线程的变量之后,线程池不新建线程时,ITL中值,依然是旧值。TTL始终是正确的。

  • 相关阅读:
    多线程(三)
    多线程(二)
    多线程(一)
    网络编程socket套接字及其使用(六)
    网络编程socket套接字及其使用(五)
    网络编程socket套接字及其使用(四)
    网络编程socket套接字及其使用(三)
    网络编程socket套接字及其使用(二)
    网络编程socket套接字及其使用(一)
    html快速入门
  • 原文地址:https://www.cnblogs.com/LittleSix/p/15818748.html
Copyright © 2011-2022 走看看