TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题.
ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑
之前为了能让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 的问题.的更多相关文章
- android线程与线程池-----线程池(二)《android开发艺术与探索》
android 中的线程池 线程池的优点: 1 重用线程池中的线程,避免了线程的创建和销毁带来的性能开销 2 能有效的控制最大并发数,避免大量线程之间因为喜欢抢资源而导致阻塞 3 能够对线程进行简单的 ...
- C# 显式创建线程 or 使用线程池线程--new Thread() or ThreadPool.QueueUserWorkItem()
在C#多线程编程中,关于是使用自己创建的线程(Thread)还是使用线程池(ThreadPool)线程,一直很困惑,知道看了Jeffrey Richter的相关介绍才明白,记录如下: 当满足一下任何条 ...
- java 线程池线程忙碌且阻塞队列也满了时给一个拒接的详细报告
线程池线程忙碌且阻塞队列也满了时给一个拒接的详细报告.下面是一个自定义的终止策略类,继承了ThreadPoolExecutor.AbortPolicy类并覆盖了rejectedExecution方法把 ...
- 线程池线程数与(CPU密集型任务和I/O密集型任务)的关系
近期看了一些JVM和并发编程的专栏,结合自身理解,来做一个关于(线程池线程数与(CPU密集型任务和I/O密集型任务)的关系)的总结: 1.任务类型举例: 1.1: CPU密集型: 例如,一般我们系统的 ...
- EventStore .NET API Client在使用线程池线程同步写入Event导致EventStore连接中断的问题研究
最近,在使用EventStore的.NET Client API采用大量线程池线程同步写入Event时(用于模拟ASP.NET服务端大并发写入Event的情况),发现EventStore的连接会随机中 ...
- Java多线程面试题:线程锁+线程池+线程同步等
1.并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对变量 ...
- 通过transmittable-thread-local源码理解线程池线程本地变量传递的原理
前提 最近一两个月花了很大的功夫做UCloud服务和中间件迁移到阿里云的工作,没什么空闲时间撸文.想起很早之前写过ThreadLocal的源码分析相关文章,里面提到了ThreadLocal存在一个不能 ...
- 线程池如何复用一个线程-- ThreadPoolExecutor的实现(未完)
任务是一组逻辑工作单元,而线程则是使任务异步执行的机制.在Java中,Runnable对象代表一个任务,Thread对象负责创建一个线程执行这个任务. 前提:1. 程序需要处理大量任务 2. 任务的执 ...
- 001-多线程-JUC线程池-线程池架构-Executor、ExecutorService、ThreadPoolExecutor、Executors
一.概述 1.1.线程池架构图 1. Executor 它是"执行者"接口,它是来执行任务的.准确的说,Executor提供了execute()接口来执行已提交的 Runnable ...
随机推荐
- Java项目收藏
数据库 MyCat:数据库中间件 IM.消息推送 t-io:不仅仅是百万级即时通讯框架 tio-im:基于t-io写的IM,主要目标降低即时通讯门槛,实现多端不同协议间的消息发送如http.webso ...
- android:View的setTag和getTag
Adapter 有个getView方法,可以使用setTag把查找的view缓存起来方便多次重用 public View getView(int position, View convertView, ...
- 【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
1.首先,java程序启动在linux,怎么生成dump文件? 1>第一步,首先你需要得到java程序的PID,最简单的方法使用如下命令 ps -ef|grep java 或者如果是docker ...
- Knockout.Js官网学习(Mapping高级用法二)
使用ignore忽略不需要map的属性 如果在map的时候,你想忽略一些属性,你可以使用ignore累声明需要忽略的属性名称集合: " }; var mapping = { 'ignore' ...
- SpringMVC类型转换、数据绑定详解
public String method(Integer num, Date birth) { ... } Http请求传递的数据都是字符串String类型的,上面这个方法在Controller中定义 ...
- CentOS下安装配置NFS并通过Java进行文件上传下载
1:安装NFS (1)安装 yum install nfs-utils rpcbind (2)启动rpcbind服务 systemctl restart rpcbind.service 查看服务状态 ...
- flex bison
https://www.gnu.org/software/bison/manual/bison.html https://blog.csdn.net/sirouni2003/article/detai ...
- RabbitMQ ——“Hello World”
介绍 RabbitMQ是一个消息实体服务(broker):它接收及转发消息.你可以把它想象成一个邮局:当你把你想要寄送的邮件放进邮箱里时,你能够确信邮局的派送员最终会把你的这封邮局送到这信的收件者手中 ...
- OkHttp踩坑记:为何 response.body().string() 只能调用一次?
想必大家都用过或接触过 OkHttp,我最近在使用 Okhttp 时,就踩到一个坑,在这儿分享出来,以后大家遇到类似问题时就可以绕过去. 只是解决问题是不够的,本文将 侧重从源码角度分析下问题的根本, ...
- Instrumentation 功能介绍(javaagent)
利用 Java 代码,即 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中 ...