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始终是正确的。

 

posted @ 2022-01-18 17:09  小陆六  阅读(399)  评论(0编辑  收藏  举报