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. android线程与线程池-----线程池(二)《android开发艺术与探索》

    android 中的线程池 线程池的优点: 1 重用线程池中的线程,避免了线程的创建和销毁带来的性能开销 2 能有效的控制最大并发数,避免大量线程之间因为喜欢抢资源而导致阻塞 3 能够对线程进行简单的 ...

  2. C# 显式创建线程 or 使用线程池线程--new Thread() or ThreadPool.QueueUserWorkItem()

    在C#多线程编程中,关于是使用自己创建的线程(Thread)还是使用线程池(ThreadPool)线程,一直很困惑,知道看了Jeffrey Richter的相关介绍才明白,记录如下: 当满足一下任何条 ...

  3. java 线程池线程忙碌且阻塞队列也满了时给一个拒接的详细报告

    线程池线程忙碌且阻塞队列也满了时给一个拒接的详细报告.下面是一个自定义的终止策略类,继承了ThreadPoolExecutor.AbortPolicy类并覆盖了rejectedExecution方法把 ...

  4. 线程池线程数与(CPU密集型任务和I/O密集型任务)的关系

    近期看了一些JVM和并发编程的专栏,结合自身理解,来做一个关于(线程池线程数与(CPU密集型任务和I/O密集型任务)的关系)的总结: 1.任务类型举例: 1.1: CPU密集型: 例如,一般我们系统的 ...

  5. EventStore .NET API Client在使用线程池线程同步写入Event导致EventStore连接中断的问题研究

    最近,在使用EventStore的.NET Client API采用大量线程池线程同步写入Event时(用于模拟ASP.NET服务端大并发写入Event的情况),发现EventStore的连接会随机中 ...

  6. Java多线程面试题:线程锁+线程池+线程同步等

    1.并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对变量 ...

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

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

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

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

  9. 001-多线程-JUC线程池-线程池架构-Executor、ExecutorService、ThreadPoolExecutor、Executors

    一.概述 1.1.线程池架构图 1. Executor 它是"执行者"接口,它是来执行任务的.准确的说,Executor提供了execute()接口来执行已提交的 Runnable ...

随机推荐

  1. Hessian学习总结(二)——使用hessian上传文件

    hessian较早版本通过 byte[] 进行文件传输:4.0之后支持 InputStream 作为参数或返回值进行传输. 注意:hessian会读取整个文件,如果文件过大,会导致JVM内存溢出.可以 ...

  2. 在Windows上使用CMake+CMakeLists.txt生成VS项目编译DlibDotnet库

    一.下次源库 地址:https://github.com/takuya-takeuchi/DlibDotNet 二.下载CMake3以上版本 地址:https://cmake.org/download ...

  3. C# System.Collections.Queue

    using System; using System.Collections; public class SamplesQueue { public static void Main() { // C ...

  4. oracle数据库将一列的值拼接成一行,并且各个值之间用逗号隔开

    使用场景:把某一列值转换为逗号分隔的字符串 例子:比如查询所有的的表空间如下,现在要获得所有的表空间用逗号分隔的字符串(比如rman duplicate的时候skip表空间) SQL> sele ...

  5. Remmina剪切板不正常的问题

    引用:http://forum.ubuntu.org.cn/viewtopic.php?f=73&p=3135388&sid=399b5566833c294045795a4b328fb ...

  6. Microsoft/Git-Credential-Manager-for-Mac-and-Linux

    纠正Mac上的错误: Fatal: java.lang.Error encountered. Details: unexpected errorfatal: credential helper '!/ ...

  7. device eth0 does not seem to be present, delaying initialization(转)

    vmlite虚拟机启动出错,就把这个虚拟机删除掉重新建立,系统虚拟硬盘使用之前的,启动系统后不能上网,通过ifconfig查看网卡没启动,遂启动网卡服务,但是出错,就是:device eth0 doe ...

  8. 【C#】C#中的属性与字段

    目录结构: contents structure [+] 属性和字段的区别 无参属性 自动实现的属性 对象和集合初始化器 匿名类型 System.Tuple类型 有参属性 属性的可访问性 在这篇文章中 ...

  9. [AaronYang]那天有个小孩跟我说Js正则

    按照自己的思路学习Node.Js 随心出发.突破正则冷门知识点,巧妙复习正则常用知识点 标签:AaronYang  茗洋  Node.Js 正则 Javascript 本篇博客地址:http://ww ...

  10. 提取aar 包中的jar包,反编译再替换成新的aar

      参考了 http://blog.csdn.net/hekewangzi/article/details/44676797 针对aar包,增加一些说明 aar包本质应该是zip文件.可以用360解压 ...