当前位置: 首页 > article >正文

ThreadLocal、InheritableThreadLocal、TransmittableThreadLocal 区别,使用场景 示例

总结:
ThreadLocal:set,get 需要再同一个线程中执行,父子线程不支持
InheritableThreadLocal:支持父子线程,不支持线程池
TransmittableThreadLocal :以上都支持

代码示例
1 pom.xml

<!-- 阿里线程传递值 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>transmittable-thread-local</artifactId>
            <version>2.14.3</version>
        </dependency>

2 ThreadLocal,InheritableThreadLocal 对比

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;

public class InheritableThreadLocalExample {

    static Logger logger = LoggerFactory.getLogger(InheritableThreadLocalExample.class);

    /**
     * 输出结果
     *  [main] [traceId:] - userName:张三
     *  [thread1] [traceId:] - userName:null
     * @throws InterruptedException
     */
    private static void threadLocalTest() throws InterruptedException {
        ThreadLocal<String> userNameTL = new ThreadLocal<>();

        //这里是主线程,ThreadLocal中设置了值:张三
        userNameTL.set("张三");
        logger.info("userName:{}", userNameTL.get());

        //创建了一个子线程thread1,在子线程中去ThreadLocal中拿值,能否拿到刚才放进去的“张三”呢?
        new Thread(() -> {
            logger.info("userName:{}", userNameTL.get());
        }, "thread1").start();

        TimeUnit.SECONDS.sleep(1);
    }

    /**
     * 输出结果
     *  [main] [traceId:] - userName:张三
     *  [thread1] [traceId:] - userName:张三
     *
     * @throws InterruptedException
     */
    private static void inheritableThreadLocal() throws InterruptedException {

        InheritableThreadLocal<String> userNameItl = new InheritableThreadLocal<>();

        //这里是主线程,使用 InheritableThreadLocal.set 放入值:张三
        userNameItl.set("张三");
        logger.info("userName:{}", userNameItl.get());

        //创建了一个子线程thread1,在子线程中去ThreadLocal中拿值,能否拿到刚才放进去的“张三”呢?
        new Thread(() -> {
            logger.info("userName:{}", userNameItl.get());
        }, "thread1").start();
        TimeUnit.SECONDS.sleep(1);
    }

    public static void main(String[] args) throws InterruptedException {
        threadLocalTest();

        System.out.println();

        inheritableThreadLocal();
    }
}

3 InheritableThreadLocal ,TransmittableThreadLocal  对比

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TransmittableThreadLocalExample {

    static Logger logger = LoggerFactory.getLogger(TransmittableThreadLocalExample.class);

    /**
     * 输出结果
     *  [main] [traceId:] - userName:张三
     *  [pool-1-thread-1] [traceId:] - 第1次获取 userName:张三
     *  [main] [traceId:] - userName:李四
     *  [pool-1-thread-1] [traceId:] - 第2次获取 userName:张三
     *
     * @throws InterruptedException
     */
    private static void fangfa_Inheri_test() throws InterruptedException {

        InheritableThreadLocal<String> userNameTtl = new InheritableThreadLocal<String>();

        // 为了看到效果,这里创建大小为1的线程池,注意这里为1才能方便看到效果
        ExecutorService executorService = Executors.newFixedThreadPool(1);

        // 主线程中设置 张三
        userNameTtl.set("张三");
        logger.info("userName:{}", userNameTtl.get());

        // 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的张三?
        executorService.execute(() -> {
            logger.info("第1次获取 userName:{}", userNameTtl.get());
        });
        TimeUnit.SECONDS.sleep(1);

        // 这里放入了李四
        userNameTtl.set("李四");
        logger.info("userName:{}", userNameTtl.get());

        // 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的李四?
        executorService.execute(() -> {
            // 在线程池中通过 inheritableThreadLocal 拿值,看看能否拿到?
            logger.info("第2次获取 userName:{}", userNameTtl.get());
        });

        TimeUnit.SECONDS.sleep(1);
    }

    /**
     * 输出结果
     *  [main] [traceId:] - userName:张三
     *  [pool-1-thread-1] [traceId:] - 第1次获取 userName:张三
     *  [main] [traceId:] - userName:李四
     *  [pool-1-thread-1] [traceId:] - 第2次获取 userName:李四
     *
     * @throws InterruptedException
     */
    private static void fangfa_Transmit_test() throws InterruptedException {

        TransmittableThreadLocal<String> userNameTtl = new TransmittableThreadLocal<String>();

        // 为了看到效果,这里创建大小为1的线程池,注意这里为1才能方便看到效果
        ExecutorService executorService = Executors.newFixedThreadPool(1);

        // 这里需要用 TtlExecutors.getTtlExecutorService 将原线程池包装下
        executorService = TtlExecutors.getTtlExecutorService(executorService);

        // 主线程中设置 张三
        userNameTtl.set("张三");
        logger.info("userName:{}", userNameTtl.get());

        // 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的张三?
        executorService.execute(() -> {
            logger.info("第1次获取 userName:{}", userNameTtl.get());
        });
        TimeUnit.SECONDS.sleep(1);

        // 这里放入了李四
        userNameTtl.set("李四");
        logger.info("userName:{}", userNameTtl.get());

        // 在线程池中通过 TransmittableThreadLocal 拿值,看看能否拿到 刚才放入的李四?
        executorService.execute(() -> {
            // 在线程池中通过 inheritableThreadLocal 拿值,看看能否拿到?
            logger.info("第2次获取 userName:{}", userNameTtl.get());
        });

        TimeUnit.SECONDS.sleep(1);
    }


    public static void main(String[] args) throws InterruptedException {
        fangfa_Inheri_test();

        System.out.println();

        fangfa_Transmit_test();
    }
}


http://www.kler.cn/news/312950.html

相关文章:

  • 【busybox记录】【shell指令】kill
  • Idea开发Gradle多模块项目踩坑纪实之一:Java模块无法执行
  • 【sql】MySQL中去重处理的方法
  • SpringMVC 处理 Ajax 请求
  • 【204】C++的vector删除重复元素
  • Java 基础篇:环境搭建、基本语法与面向对象编程
  • 【JPCS出版】第二届应用统计、建模与先进算法国际学术会议(ASMA2024,9月27日-29)
  • 华为OD机试真题- MELON的难题-2024年OD统一考试(E卷)
  • Leetcode 416. 分割等和子集(Medium)
  • 【第34章】Spring Cloud之SkyWalking分布式日志
  • 程序人生-2024我的个人总结
  • VScode开发GD32移植(标准库通用),保姆级!!!!!!!
  • OCR两篇革命之作
  • C#区分值类型和引用类型【一文读懂】
  • 第十三周:机器学习笔记
  • 【开发语言】写程序的两大基本原则(PO和NT原则)
  • three.js 热力图
  • Android Perfetto 学习
  • 聚焦于 Web 性能指标 TTI
  • 2024新动态:低代码开发占领新常态市场
  • ImportError: DLL load failed while importing _ssl: 找不到指定的模块的解决方法
  • man 命令:查看命令的帮助信息
  • 【学习资料】袋中共36个球,红白黑格12个,问能一次抽到3个红4个白5个黑的概率是多少?
  • 封装一个录音声音振动效果的组件
  • foc原理odrive驱动板的使用,以及功能介绍
  • 基于TRIZ的救援机器人轻量化设计
  • 搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(一)-概述
  • 翻唱技巧:AU和Cubase翻唱录制对轨技巧
  • Linux 系统进程理解——标识符,状态
  • uniapp中使用echarts 完整步骤,包括报错以及解决方案