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 的问题相关推荐

  1. java.线程池 线程数_如何在线程“ main”中修复异常java.lang.NoClassDefFoundError:Java中的org / slf4j / LoggerFactory...

    java.线程池 线程数 此错误表示您的代码或您在应用程序中使用的任何外部库都在使用SLF4J库 (一个开放源代码日志记录库),但无法找到所需的JAR文件,例如slf4j-api-1.7.2.jar因 ...

  2. 【Android 异步操作】线程池 ( 线程池使用示例 | 自定义线程池使用流程 | 自定义任务拒绝处理策略 | 完整代码示例 )

    文章目录 一.自定义线程池使用流程 二.自定义任务拒绝处理策略 三.完整代码示例 在博客 [Android 异步操作]线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTas ...

  3. 【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )

    文章目录 一.线程池 reject 拒绝任务 二.线程池 addWorker 添加任务 在上一篇博客 [Android 异步操作]线程池 ( 线程池 execute 方法源码解析 ) 中 , 讲解 线 ...

  4. 【Android 异步操作】线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTask 使用线程池示例 )

    文章目录 一.线程池简介 二.线程池初始化方法简介 三.线程池使用示例 一.线程池简介 线程池一般是实现了 ExecutorService 接口的类 , 一般使用 ThreadPoolExecutor ...

  5. 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )

    文章目录 一.线程池作用 二.线程池种类 三.线程池工作机制 四.线程池任务调度源码解析 一.线程池作用 线程池作用 : ① 避免创建线程 : 避免每次使用线程时 , 都需要 创建线程对象 ; ② 统 ...

  6. TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题.

    ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑 TransmittableThreadLocal 原理 之前为了能让InheritableThr ...

  7. 通过transmittable-thread-local源码理解线程池线程本地变量传递的原理

    前提 最近一两个月花了很大的功夫做UCloud服务和中间件迁移到阿里云的工作,没什么空闲时间撸文.想起很早之前写过ThreadLocal的源码分析相关文章,里面提到了ThreadLocal存在一个不能 ...

  8. java线程池是如何复用线程_线程池如何复用一个线程-- ThreadPoolExecutor的实现(未完)...

    任务是一组逻辑工作单元,而线程则是使任务异步执行的机制.在Java中,Runnable对象代表一个任务,Thread对象负责创建一个线程执行这个任务. 前提:1. 程序需要处理大量任务 2. 任务的执 ...

  9. Java 线程池的复用原理

    线程池的运行图 在线程池中,线程会从 workQueue 中读取任务来执行,最小的执行单位就是 Worker,Worker 实现了 Runnable 接口,重写了 run 方法,这个 run 方法是让 ...

最新文章

  1. 在linux上配置JDK环境变量
  2. D3.js比例尺 定量比例尺 之 线性比例尺(v3版本)
  3. (chap9 基于HTTP的功能追加协议) WebSocket使用浏览器进行全双工通信
  4. anydesk截屏技术
  5. Delphi 26 岁
  6. 牛客题霸 [ 旋转数组] C++题解/答案
  7. swift面向对象之多态与继承
  8. Ubuntu ICEauthority error
  9. php7.1 win7,win7 配置AMP环境(apache2.4.39 + php7.1.28)
  10. 单片机C语言入门自学指南(前期准备)
  11. DDos攻击防御策略
  12. c语言 字符串提取连续数字,c语言一串字符串中提取数字并相加的问题
  13. 高级计量经济学及stata应用 学习笔记③ 长面板
  14. 二十六 .ajax登录 认证 验证码(session)
  15. 区块链技术要用到什么开发语言?
  16. 【Educoder】Python学习记录(二)
  17. Jetpack Compose--声明式UI替代传统命令式UI的新产品
  18. 错误:‘CV_RETR_EXTERNAL’在此作用域中尚未声明
  19. 论文篇:教你如何用chatgpt辅助写论文文献综述
  20. 抖音矩阵系统,这个排名很难啊。按?

热门文章

  1. 怎么用git将本地代码上传到远程服务器_git命令 将本地代码上传到远程服务器...
  2. Docker的四种网络模式和相关网络命令等操作
  3. linux笔记之 搭建本地yum源,网卡的基本操作
  4. 无头结点单链表的逆置_第1章第2节练习题11 就地逆置单链表
  5. html body background color,HTML Style backgroundColor用法及代码示例
  6. wxif 判断字符串相等_ES6:字符串、数组、对象的扩展
  7. mysql数据库比较语句,六条比较有用的MySQL数据库操作的SQL语句小结
  8. python自然语言处理评论_python自然语言处理——学习笔记:Chapter3纠错
  9. vuecli启动的服务器位置,在vue cli 3生成的项目中启动dev服务器
  10. 计算机应用基础在线测试01,计算机应用基础在线测试(全部正确).pdf