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

ITL和TTL线程间值的传递

InheritableThreadLocal

InheritableThreadLocal 继承自 ThreadLocal,增加了父线程到子线程的值传递功能。当一个新线程被创建时,InheritableThreadLocal 会将父线程中 ThreadLocal 变量的值拷贝到子线程(浅拷贝),子线程后续对值的修改不会影响到父线程,同时父线程后续对值的修改也不会反映到已经创建的子线程中。ITL在线程池的模式下,就没办法再正确传递。

TransmittableThreadLocal

TransmittableThreadLocal 继承自 InheritableThreadLocal,同样支持父线程到子线程的值传递功能,但在线程池的模式下,可以正确传递,但需要配合TtlExecutors线程池一起使用。

package com.example.demo.test;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TransmittableThreadLocalTest {// 需要注意的是,使用TTL的时候,要想传递的值不出问题,线程池必须得用TTL加一层代理(下面会讲这样做的目的)
//  private static ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));private static ExecutorService executorService = Executors.newFixedThreadPool(2);private static ThreadLocal tl = new InheritableThreadLocal<>(); //这里采用TTL的实现public static void main(String[] args) {new Thread(() -> {String mainThreadName = "main_01";tl.set(1);executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之前(1), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});sleep(100L); //确保上面的会在tl.set执行之前执行tl.set(2); // 等上面的线程池第一次启用完了,父线程再给自己赋值executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之后(2), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));}).start();new Thread(() -> {String mainThreadName = "main_02";tl.set(3);executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之前(3), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});sleep(100L); //确保上面的会在tl.set执行之前执行tl.set(4); // 等上面的线程池第一次启用完了,父线程再给自己赋值executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});executorService.execute(() -> {sleep(1L);System.out.println(String.format("本地变量改变之后(4), 父线程名称-%s, 子线程名称-%s, 变量值=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));});System.out.println(String.format("线程名称-%s, 变量值=%s", Thread.currentThread().getName(), tl.get()));}).start();}private static void sleep(long time) {try {Thread.sleep(time);} catch (InterruptedException e) {e.printStackTrace();}}
}
http://www.xdnf.cn/news/121051.html

相关文章:

  • AI工程pytorch小白TorchServe部署模型服务
  • nginx
  • DNS域名解析服务
  • 滚珠螺杆在数控机床中如何降低摩擦系数?
  • 植物信号转导概述——学习植物的交流方式
  • Spring Boot 中触发异步任务的几种方式
  • Cifar10-图像分类学习笔记(二)--将图像解析存储到TRAIN文件夹下
  • 点云配准算法之NDT算法原理详解
  • ECMAScript 2025新特性深度解析:JavaScript的又一次进化
  • 4.4 记忆机制与上下文管理:短期与长期记忆的设计与应用
  • 目标检测篇---faster R-CNN
  • 车间排产与生产调度:提升制造效率的核心引擎​
  • 涂料油墨制造数字化转型的关键技术与挑战
  • Linux编译器-gcc/g++使用
  • 网络IP冲突的成因与解决方案
  • 【Unity AR开发插件】一、高效热更新:Unity AR 插件结合 HybridCLR 与 ARFoundation 的开源仓库分享
  • JDBC插件式数据库连接器
  • IO 核心要点(1)
  • 基于 EFISH-SBC-RK3588 的无人机智能巡检终端方案‌
  • 5G/6G通信设备中的盲埋孔技术突破
  • 数据结构-查找
  • 第六章 QT基础:5、QT的UDP网络编程
  • 【前端】【业务场景】【面试】在前端开发中,如何实现实时数据更新,比如实时显示服务器推送的消息,并且保证在不同网络环境下的稳定性和性能?
  • 如何轻松将 Python 英文版切换至中文界面
  • 垂直分表和水平分表涉及的不同场景?如何决定使用水平分表还是垂直分表?
  • HT7180输入电压2.7-12V输出电压最高12.8V禾润一级代理聚能芯半导体
  • 【verilog】单/多if语句优先级
  • 大数据赋能零售,打造个性化购物新纪元
  • UML 活动图深度解析:以在线购物系统为例
  • 深入了解递归、堆与栈:C#中的内存管理与函数调用