TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题
ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑
TransmittableThreadLocal 原理
之前为了能让InheritableThreadLocal 正确传递,不得不每次
ExecutorService executor = Executors.newFixedThreadPool(>=[任务线程数]); 或者直接new Thread.这样不仅引起性能损耗,并且如果并发上来了,会造成不必要的上下文切换.还必须用信号量做并发控制. 偶然发现 阿里开源 TransmittableThreadLocal 可以解决此问题. 以下来实验一下
/*** User: laizhenwei* Date: 2018-04-12 Time: 10:07* Description:*/ public class Ttl {static ExecutorService executorService = Executors.newFixedThreadPool(1);public static void main(String[] args) {//子线程每次new 所以会复制线程的InheritableThreadLocal,结果正确 // withoutThreadPool(10);//因线程池复用线程,不会每次new 所以不会更新父线程InheritableThreadLocal 的值,导致结果错误withThreadPool(10);}public static void withoutThreadPool(int c){for(int i=0;i<c;i++){Integer var1 = (int)(Math.random()*100);Integer var2 = (int)(Math.random()*100);MyContextHolder.set(var1);threadRun(var1,var2);}}public static void withThreadPool(int c){for(int i=0;i<c;i++){Integer var1 = (int)(Math.random()*100);Integer var2 = (int)(Math.random()*100);MyContextHolder.set(var1);threadPoolExecute(var1,var2);}}public static void threadRun(Integer var1,Integer var2){new Thread(()->assert1(var1,var2)).start();}public static void threadPoolExecute(Integer var1,Integer var2){executorService.execute(()->assert1(var1,var2));}public static void assert1(Integer var1,Integer var2){System.out.println(MyContextHolder.get()*var2==var1*var2);}public static class MyContextHolder{private static ThreadLocal<Integer> stringThreadLocal = new InheritableThreadLocal<>();public static void set(Integer data) {stringThreadLocal.set(data);}public static Integer get() {return stringThreadLocal.get();}}}
withoutThreadPool(10)输出结果
withThreadPool(10); 输出结果
解决方式
pom引入
<!-- https://mvnrepository.com/artifact/com.alibaba/transmittable-thread-local --><dependency><groupId>com.alibaba</groupId><artifactId>transmittable-thread-local</artifactId><version>2.2.0</version></dependency>
修改MyContextHolder
public static class MyContextHolder{private static ThreadLocal<Integer> stringThreadLocal = new TransmittableThreadLocal<>();// private static ThreadLocal<Integer> stringThreadLocal = new InheritableThreadLocal<>();public static void set(Integer data) {stringThreadLocal.set(data);}public static Integer get() {return stringThreadLocal.get();}}
修改threadPoolExecute
public static void threadPoolExecute(Integer var1,Integer var2){//使用TransmittableThreadLocal 解决executorService.execute(TtlRunnable.get(()->assert1(var1,var2)) ); // executorService.execute(()->assert1(var1,var2));}
运行 withThreadPool(10); 结果
TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题相关推荐
- java.线程池 线程数_如何在线程“ main”中修复异常java.lang.NoClassDefFoundError:Java中的org / slf4j / LoggerFactory...
java.线程池 线程数 此错误表示您的代码或您在应用程序中使用的任何外部库都在使用SLF4J库 (一个开放源代码日志记录库),但无法找到所需的JAR文件,例如slf4j-api-1.7.2.jar因 ...
- 【Android 异步操作】线程池 ( 线程池使用示例 | 自定义线程池使用流程 | 自定义任务拒绝处理策略 | 完整代码示例 )
文章目录 一.自定义线程池使用流程 二.自定义任务拒绝处理策略 三.完整代码示例 在博客 [Android 异步操作]线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTas ...
- 【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )
文章目录 一.线程池 reject 拒绝任务 二.线程池 addWorker 添加任务 在上一篇博客 [Android 异步操作]线程池 ( 线程池 execute 方法源码解析 ) 中 , 讲解 线 ...
- 【Android 异步操作】线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTask 使用线程池示例 )
文章目录 一.线程池简介 二.线程池初始化方法简介 三.线程池使用示例 一.线程池简介 线程池一般是实现了 ExecutorService 接口的类 , 一般使用 ThreadPoolExecutor ...
- 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )
文章目录 一.线程池作用 二.线程池种类 三.线程池工作机制 四.线程池任务调度源码解析 一.线程池作用 线程池作用 : ① 避免创建线程 : 避免每次使用线程时 , 都需要 创建线程对象 ; ② 统 ...
- TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题.
ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑 TransmittableThreadLocal 原理 之前为了能让InheritableThr ...
- 通过transmittable-thread-local源码理解线程池线程本地变量传递的原理
前提 最近一两个月花了很大的功夫做UCloud服务和中间件迁移到阿里云的工作,没什么空闲时间撸文.想起很早之前写过ThreadLocal的源码分析相关文章,里面提到了ThreadLocal存在一个不能 ...
- java线程池是如何复用线程_线程池如何复用一个线程-- ThreadPoolExecutor的实现(未完)...
任务是一组逻辑工作单元,而线程则是使任务异步执行的机制.在Java中,Runnable对象代表一个任务,Thread对象负责创建一个线程执行这个任务. 前提:1. 程序需要处理大量任务 2. 任务的执 ...
- Java 线程池的复用原理
线程池的运行图 在线程池中,线程会从 workQueue 中读取任务来执行,最小的执行单位就是 Worker,Worker 实现了 Runnable 接口,重写了 run 方法,这个 run 方法是让 ...
最新文章
- 在linux上配置JDK环境变量
- D3.js比例尺 定量比例尺 之 线性比例尺(v3版本)
- (chap9 基于HTTP的功能追加协议) WebSocket使用浏览器进行全双工通信
- anydesk截屏技术
- Delphi 26 岁
- 牛客题霸 [ 旋转数组] C++题解/答案
- swift面向对象之多态与继承
- Ubuntu ICEauthority error
- php7.1 win7,win7 配置AMP环境(apache2.4.39 + php7.1.28)
- 单片机C语言入门自学指南(前期准备)
- DDos攻击防御策略
- c语言 字符串提取连续数字,c语言一串字符串中提取数字并相加的问题
- 高级计量经济学及stata应用 学习笔记③ 长面板
- 二十六 .ajax登录 认证 验证码(session)
- 区块链技术要用到什么开发语言?
- 【Educoder】Python学习记录(二)
- Jetpack Compose--声明式UI替代传统命令式UI的新产品
- 错误:‘CV_RETR_EXTERNAL’在此作用域中尚未声明
- 论文篇:教你如何用chatgpt辅助写论文文献综述
- 抖音矩阵系统,这个排名很难啊。按?
热门文章
- 怎么用git将本地代码上传到远程服务器_git命令 将本地代码上传到远程服务器...
- Docker的四种网络模式和相关网络命令等操作
- linux笔记之 搭建本地yum源,网卡的基本操作
- 无头结点单链表的逆置_第1章第2节练习题11 就地逆置单链表
- html body background color,HTML Style backgroundColor用法及代码示例
- wxif 判断字符串相等_ES6:字符串、数组、对象的扩展
- mysql数据库比较语句,六条比较有用的MySQL数据库操作的SQL语句小结
- python自然语言处理评论_python自然语言处理——学习笔记:Chapter3纠错
- vuecli启动的服务器位置,在vue cli 3生成的项目中启动dev服务器
- 计算机应用基础在线测试01,计算机应用基础在线测试(全部正确).pdf