alibaba transmittable-thread-local源码解析

本文介绍了TransmittableThreadLocal的用途,它用于弥补InheritableThreadLocal在线程池场景的不足,确保线程变量在父子线程间正确传递。文章详细讲解了ThreadLocal与InheritableThreadLocal的区别,线程池线程复用的原理,并提供了TransmittableThreadLocal的使用示例和实现原理,强调了使用时的注意事项。
摘要由CSDN通过智能技术生成

   transmittable-thread-local主要是用于线程池等线程复用时,需要确保子线程的InheritableThreadLocal变量永远跟该线程创建时的父线程的InheritableThreadLocal一致的场景下,弥补InheritableThreadLocal的不足,通常应用于方法级监控的中间件中。

一、ThreadLocal和InheritableThreadLocal的差异

       ThreadLocal 实现原理参考 https://www.cnblogs.com/dolphin0520/p/3920407.html

       InheritableThreadLocal 实现原理参考  https://blog.csdn.net/ni357103403/article/details/51970748

       总结:1、父子线程的ThreadLocal变量是互相独立的,没有任何关联的,而子线程的InheritableThreadLocal变量在初始化完成时,跟父线程的InheritableThreadLocal变量保存的对象是同一个。如果父子线程只是修改该对象属性,而没有修改对象引用,则此时InheritableThreadLocal变量等价于普通的变量。

                  2、ThreadLocal 和 InheritableThreadLocal变量都是在线程创建的时候才会初始化,线程复用的情况下,程序访问到的ThreadLocal 和 InheritableThreadLocal变量是上一次job运行完成后的可能被修改的变量。

        参考如下测试用例:

package threadLocal.test;

import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MyTest3 {

    @Test
    public void name() throws Exception{
        ThreadLocal<Map<ThreadLocal<String>,String>> threadLocal=new ThreadLocal<Map<ThreadLocal<String>,String>>(){
            @Override
            protected Map<ThreadLocal<String>,String> initialValue() {
                return new HashMap<>();
            }
        };
        InheritableThreadLocal<Map<ThreadLocal<String>,String>> inheritableThreadLocal=new InheritableThreadLocal<Map<ThreadLocal<String>,String>>(){
            @Override
            protected Map<ThreadLocal<String>,String> initialValue() {
                return new HashMap<>();
            }
        };
        Map<ThreadLocal<String>,String> threadLocalStringMap=new HashMap<>();
        InheritableThreadLocal<String> str1=new InheritableThreadLocal<>();
        str1.set("str1");
        threadLocalStringMap.put(str1, "str1");
        ThreadLocal<String> str2=new ThreadLocal<String>(){
            @Override
            protected String initialValue() {
                return Thread.currentThread().getName();
            }
        };
        str2.set("str2");
        threadLocalStringMap.put(str2, "str2");

        threadLocal.set(threadLocalStringMap);
        inheritableThreadLocal.set(threadLocalStringMap);

        ExecutorService executorService= Executors.newFixedThreadPool(1);
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("threadLocal map size-->"+threadLocal.get().size());
                System.out.println("inheritableThreadLocal map size-->"+inheritableThreadLocal.get().size());

                ThreadLocal<String> test=new ThreadLocal<>();
                test.set("test");
                threadLocal.get().put(test, "test");
                System.out.println("threadLocal map put content-->"+threadLocal.get());

                for(Map.Entry<ThreadLocal<String>,String> entry :inheritableThreadLocal.get().entrySet()){
                    System.out.println(" sub thread inheritableThreadLocal map value-->"+entry.getKey().get()+",origal value-->"+entry.getValue());
                    String randomStr=RandomStringUtils.randomNumeric(6);
                    entry.getKey().set(randomStr);
                    entry.setValue(randomStr);
                    System.out.println("sub thread set new value-->"+randomStr);
                }
            }
        };

        System.out.println("================test one================");
        executorService.submit(runnable);

        executorService.awaitTermination(2, TimeUnit.SECONDS);

        System.out.println("================test one after================");

        System.out.println(threadLocal.get().equals(inheritableThreadLocal.get()));

        for(Map.Entry<ThreadLocal<String>,String> entry :inheritableThreadLocal.get().entrySet()){
            System.out.println("main thread  threadLocal value-->"+entry.getKey().get()+",origal value-->"+entry.getValue());
        }

        str1.set("new str");
        str2.set("new str2");

        System.out.println("================test two================");
        runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("threadLocal map size-->"+threadLocal.get().size()+",content-->"+threadLocal.get());
                System.out.println("inheritableThreadLocal map size-->"+inheritableThreadLocal.get().size());

                for(Map.Entry<ThreadLocal<String>,String> entry :inheritableThreadLocal.get().entrySet()){
                    System.out.println("sub thread  inheritableThreadLocal map value-->"+entry.getKey().get()+",origal value-->"+entry.getValue());
                    String randomStr=RandomStringUtils.randomNumeric(6);
                    entry.getKey().set(randomStr);
                    entry.setValue(randomStr);
                    System.out.println("sub thread set new value-->"+randomStr);
                }
            }
        };


        executorService.submit(runnable);

        executorService.awaitTermination(2, TimeUnit.SECONDS);

        System.out.println("================test two after================");


        System.out.println(threadLocal.get().equals(inheritableThreadLocal.get()));

        for(Map.Entry<ThreadLocal<String>,String> entry :inheritableThreadLocal.get().entrySet()){
            System.out.println("main thread  threadLocal value-->"+entry.getKey().get()+",origal value-->"+entry.getValue());
        }



    }
}

          该测试用例运行的结果及说明如下:

================test one================
threadLocal 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值