转载,原文链接:http://www.cnblogs.com/goofy/archive/2011/11/11/2245907.html
跟大家分享一个问题排查的时候发现的关于ThreadLocal
的问题。
道行尚浅,如失偏颇,欢迎斧正
排查时查ic
的日志,发现记录的调用来源IP
记录错乱。查看IC
相关代码,发现记录IP
用的costomerIP
是一个static
的ThreadLocal
类变量。
之前收藏夹系统接触过ThreadLocal
,印象中是用一个Map
实现的,既然与线程有关,那么web
应用都使用了线程池来对线程进行重用,那么会不会是线程重用引起的呢?仔细看了ThreadLocal
的代码。
原来java
里的Thread
对象里有一个ThreadLocalMap
,key
是ThreadLocal
对象,value
是ThreadLocal
的值,也就是说在对ThreadLocal
赋值时其实是对当前Thread
的一个ThreadLocalMap
进行操作,而ThreadLocal
本身只是一个key
。Get
操作同理。这也解释了为什么一个静态变量在不同的线程中可以有不同的值。
ThreadLocal.set(Object
value):
public
void
set(T value) {
Thread t = Thread.currentThread
();
ThreadLocalMap
map = getMap(t);
if
(
map
!=
null
)
map.set(
this
, value);
else
createMap(t, value);
}
这样就漂亮实现了一个线程独立的value holder
,当然还有很多细节的处理。但是如果使用不小心就会出问题。
比如这里线程池会对线程进行重用,但是重用时并且不会重置其中的ThreadLocalMap
,一个请求过来时,可能并没有新起一个线程,而是重用之前的一个线程,这时如果这个ThreadLocal
没有进行set
,那么直接get
出来的可能就是之前请求时set
的值,就会出现前面提到的ip
记录错乱的问题。所以使用ThreadLocal
,一定要保证get
之前进行过set
。
package
tk.mysweetie.java.test;
import
java.util.concurrent.ArrayBlockingQueue;
import
java.util.concurrent.ThreadPoolExecutor;
import
java.util.concurrent.TimeUnit;
/**
*
@author
wangzhengyang.pt
* 使用TreadPool时的ThreadLocal示例
*/
public
class
TestThreadPool {
private
static
ThreadLocal<Boolean> bol = new
ThreadLocal<Boolean>();
/**
* 第二个提交的Runnable没有对TreadLocal进行set,但是已经被set过了
*/
public
static
void
main(String[] args) {
ThreadPoolExecutor pool = new
ThreadPoolExecutor(1, 1, 100, TimeUnit. SECONDS ,
new
ArrayBlockingQueue<Runnable>(1), new
ThreadPoolExecutor.AbortPolicy() );
//
进行set的Runnable
pool.execute(new
Runnable() {
@Override
public
void
run() {
/**
*set为true**
*/
bol.set(true
);
System.out.println("" + Thread.currentThread() + "seted bol:" + bol.get());
}
});
//
没有set的Runnable
pool.execute(new
Runnable() {
@Override
public
void
run() {
System.out.println("" + Thread.currentThread() + "not seted bol:" + bol.get());
}
});
}
}
分享到:
相关推荐
Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...
以上就是关于ThreadLocal的基本概念、使用方法、生命周期管理和实际应用示例的详细解释。了解并熟练掌握ThreadLocal可以帮助我们编写出更高效、更安全的多线程代码。在Java并发编程中,ThreadLocal是一个不可或缺的...
以下是一个简单的ThreadLocal使用示例,展示了如何为每个线程创建一个独立的`SimpleDateFormat`实例: ```java package com.javapapers; import java.text.SimpleDateFormat; import java.util.Date; public ...
Java中的`ThreadLocal`类是...但是,使用时需注意其潜在的内存泄漏风险和对代码可读性的影响,合理地选择使用场景。通过理解和掌握`ThreadLocal`的工作原理,我们可以更有效地利用它来优化多线程程序的性能和可维护性。
深入理解ThreadLocal工作原理及使用示例 ThreadLocal是Java提供的一种解决多线程程序并发问题的工具类,自JDK1.2版本以来提供了java.lang.ThreadLocal类。ThreadLocal的主要作用是为每个使用该变量的线程提供独立的...
因此,建议在不再使用ThreadLocal时调用`remove()`方法清除对应的变量副本。 总之,ThreadLocal是Android开发中解决线程间数据隔离问题的一个重要工具,合理使用它可以提高代码的可读性和安全性。在实际开发中,...
ThreadLocal内部使用了一个ThreadLocalMap,它是一个基于ThreadLocal实例作为键,值为用户存储对象的弱引用表。每个线程都有一个这样的ThreadLocalMap,保证了线程间数据的隔离。 6. **工具支持** 在实际开发中,...
以下是一个完整的ThreadLocal示例,演示了如何在一个Runnable实例中使用ThreadLocal: ```java public class ThreadLocalExample { public static class MyRunnable implements Runnable { private ThreadLocal...
4. **减少锁的使用**: 当多个线程需要共享同一资源,但每个线程只需要读取自己相关的数据时,`ThreadLocal`可以避免锁的使用,提升效率。 **注意事项** - 使用`ThreadLocal`后,应确保及时清理不再使用的变量,...
Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,...总之,ThreadLocal是Java多线程编程中的一个强大工具,但使用时需谨慎,理解其工作原理和潜在风险,才能更好地利用它来解决实际问题。
### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本...因此,在使用`ThreadLocal`时,应当充分理解其工作机制,合理规划其生命周期,并适时进行资源清理,以确保系统的稳定性和性能。
因此,开发者在使用ThreadLocal时必须小心,避免在ThreadLocal中存储长期有效的数据,防止其他线程意外访问。 误区四:ThreadLocal可以随意多用 ThreadLocal虽然能提供方便的线程隔离,但过度依赖ThreadLocal可能...
本篇文章将聚焦于Spring事务处理中ThreadLocal的使用,以及如何通过源码理解和应用这个工具。 首先,了解Spring事务管理的基本概念。在多线程环境中,事务管理是至关重要的,它负责确保一组数据库操作要么全部成功...
总结:`ThreadLocal` 是一个强大的工具,但在使用时必须谨慎,尤其是在多线程环境中,如 Tomcat 这样的 Web 容器。如果不正确地管理 `ThreadLocal` 的生命周期,可能导致类加载器级别的内存泄漏。理解 `ThreadLocal`...
4. 不再使用时,调用remove方法清除线程局部变量,防止内存泄漏。 接下来,我们转向Spring框架的事务管理。Spring提供了声明式事务管理,开发者无需显式地编写事务管理代码,只需在配置文件或注解中声明事务属性,...
**标题:“JDK的ThreadLocal理解(一)使用和测试”** **正文:** ThreadLocal是Java中的一个非常重要的线程安全工具类,它在多线程...然而,使用时也要注意避免内存泄漏和过度依赖,合理规划其在系统架构中的位置。
这个压缩包 "Quartz-ThreadLocal.rar" 内含的学习资源很可能是关于如何在 Quartz 调度器中结合使用 ThreadLocal 的示例。 Quartz 的核心功能包括: 1. **作业与触发器**:在 Quartz 中,任务被称为“作业”(Job)...