ThreadLocal遇到线程池时, 各线程间的数据会互相干扰, 串来串去

最近遇到一个比较隐蔽而又简单地问题,在使用ThreadLocal时发现出现多个线程中值串来串去,排查一番,确定问题为线程池的问题,线程池中的线程是会重复利用的,而ThreadLocal是用线程来做Key的所以在使用线程池的时候要特别注意ThreadLocal. 
ThreadLocal数据是在线程创建时绑定在线程上的, 所以解决方法是在使用数据之前调用remove() 移除掉之前的其他线程产生的数据

解决方法

重构remove方法 
@Override 
public void remove() { 
super.remove(); 
initialValue(); 

先remove, 然后再初始化一次, 这样就可以保证数据是干净的了.

当然你也可以在调用的finally里面使用remove, 也是可以的.

时间: 2024-11-08 17:15:16

ThreadLocal遇到线程池时, 各线程间的数据会互相干扰, 串来串去的相关文章

线程池和异步线程

目录: 1 什么是CLR线程池? 2 简单介绍下线程池各个优点的实现细节 3 线程池ThreadPool的常用方法介绍 4 简单理解下异步线程 5 异步线程的工作过程和几个重要的元素 6 有必要简单介绍下Classic Async Pattern 和Event-based Async Pattern 7 异步线程的发展趋势以及.net4.5异步的简化 8 本章示例 自定义一个简单的线程池 Asp.net异步IHttpAsyncHandler示例 9 本章总结 1 什么是CLR线程池? 在上一章中

在使用线程池时应特别注意对ThreadLocal的使用

使用ThreadLocal并且有线程池时要特别注意,ThreadLocal是以线程为key的,而线程池里面的线程是会被重新利用的,所以如果有使用线程池并且使用ThreadLocal来保存状态信息时要特别注意要每次初始化,否则同一个线程会用到之前线程的状态信息,代码见 http://www.macrohuang.com/blog/?p=34 其他:http://blog.csdn.net/comliu/article/details/3186778http://www.blogjava.net/j

当面试官问线程池时,你应该知道些什么?

Java面试中,线程池也算是一个高频的问题,其实就JDK源码来看线程池这一块的实现代码应该算是写的清晰易懂的,通过这篇文章,我们就来盘点一下线程池的知识点. 本文基于JDK1.8源码进行分析 首先看下线程池构造函数: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, Threa

使用线程池与专用线程

高效线程使用圣典 严格来讲,线程的系统开销很大.系统必须为线程分配并初始化一个线程内核对象,还必须为每个线程保留1MB的地址空间(按需提交)用于线程的用 户模式堆栈,分配12KB左右的地址空间用于线程的内核模式堆栈.然后,紧接着线程创建后,Windows调用进程中每个DLL都有的一个函数来通知进程 中所有的DLL操作系统创建了一个新的线程.同样,销毁一个线程的开销也不小:进程中的每个DLL都要接收一个关于线程即将"死亡"的通知,而且内核对象 及堆栈还需释放. 如果一台计算机中只有一个C

Android 线程池来管理线程

网上讲了很多的关于线程池的例子.其实在我们实际应用中,譬如说,一个应用的线程是怎样来管理的,我们就可以说,我们可以使用线程池来管理线程. eg: class DianLiang1 implements Runnable { @Override punlic void Run{ system.println("*************111111111111111111111****************"); } } class DianLiang2 implements Runn

深入浅出 Java Concurrency (33): 线程池 part 6 线程池的实现及原理 (1)[转]

线程池数据结构与线程构造方法 由于已经看到了ThreadPoolExecutor的源码,因此很容易就看到了ThreadPoolExecutor线程池的数据结构.图1描述了这种数据结构. 图1 ThreadPoolExecutor 数据结构 其实,即使没有上述图形描述ThreadPoolExecutor的数据结构,我们根据线程池的要求也很能够猜测出其数据结构出来. 线程池需要支持多个线程并发执行,因此有一个线程集合Collection<Thread>来执行线程任务: 涉及任务的异步执行,因此需要

Java多线程系列--“JUC线程池”04之 线程池原理(三)

本章介绍线程池的生命周期. 线程有5种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态.线程池也有5种状态:然而,线程池不同于线程,线程池的5种状态是:Running, SHUTDOWN, STOP, TIDYING, TERMINATED. 线程池状态定义代码如下: /** * The main pool control state, ctl, is an atomic integer packing * two conceptual fields * workerCount, indi

Java多线程系列--“JUC线程池”02之 线程池原理(一)

ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存放一定数量线程的一个线程集合.线程池允许同时运行的线程数量就是线程池的容量:当添加到线程池中的线程超过它的容量时,会有一部分线程阻塞等待.线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理." ThreadPoolExecutor数据结构 ThreadPoolExecutor的数据结构如下图所示: 各个数据在ThreadPoolExecutor

Java多线程系列--“JUC线程池”01之 线程池架构

概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构图线程池示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509903.html 线程池架构图 线程池的架构图如下: 1. Executor 它是"执行者"接口,它是来执行任务的.准确的说,Executor提供了execute()接口来执行