`
zhoushu126
  • 浏览: 81683 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

使用TreadPool时的ThreadLocal示例

 
阅读更多

转载,原文链接:http://www.cnblogs.com/goofy/archive/2011/11/11/2245907.html

 

跟大家分享一个问题排查的时候发现的关于ThreadLocal 的问题。 道行尚浅,如失偏颇,欢迎斧正

 

排查时查ic 的日志,发现记录的调用来源IP 记录错乱。查看IC 相关代码,发现记录IP 用的costomerIP 是一个staticThreadLocal 类变量。

 

之前收藏夹系统接触过ThreadLocal ,印象中是用一个Map 实现的,既然与线程有关,那么web 应用都使用了线程池来对线程进行重用,那么会不会是线程重用引起的呢?仔细看了ThreadLocal 的代码。

 

原来java 里的Thread 对象里有一个ThreadLocalMapkeyThreadLocal 对象,valueThreadLocal 的值,也就是说在对ThreadLocal 赋值时其实是对当前Thread 的一个ThreadLocalMap 进行操作,而ThreadLocal 本身只是一个keyGet 操作同理。这也解释了为什么一个静态变量在不同的线程中可以有不同的值。


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示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...

    ThreadLocal应用示例及理解

    以上就是关于ThreadLocal的基本概念、使用方法、生命周期管理和实际应用示例的详细解释。了解并熟练掌握ThreadLocal可以帮助我们编写出更高效、更安全的多线程代码。在Java并发编程中,ThreadLocal是一个不可或缺的...

    ThreadLocal

    以下是一个简单的ThreadLocal使用示例,展示了如何为每个线程创建一个独立的`SimpleDateFormat`实例: ```java package com.javapapers; import java.text.SimpleDateFormat; import java.util.Date; public ...

    java中ThreadLocal类的使用

    Java中的`ThreadLocal`类是...但是,使用时需注意其潜在的内存泄漏风险和对代码可读性的影响,合理地选择使用场景。通过理解和掌握`ThreadLocal`的工作原理,我们可以更有效地利用它来优化多线程程序的性能和可维护性。

    深入理解ThreadLocal工作原理及使用示例

    深入理解ThreadLocal工作原理及使用示例 ThreadLocal是Java提供的一种解决多线程程序并发问题的工具类,自JDK1.2版本以来提供了java.lang.ThreadLocal类。ThreadLocal的主要作用是为每个使用该变量的线程提供独立的...

    Android 中 ThreadLocal使用示例

    因此,建议在不再使用ThreadLocal时调用`remove()`方法清除对应的变量副本。 总之,ThreadLocal是Android开发中解决线程间数据隔离问题的一个重要工具,合理使用它可以提高代码的可读性和安全性。在实际开发中,...

    使用ThreadLocal管理“session”数据

    ThreadLocal内部使用了一个ThreadLocalMap,它是一个基于ThreadLocal实例作为键,值为用户存储对象的弱引用表。每个线程都有一个这样的ThreadLocalMap,保证了线程间数据的隔离。 6. **工具支持** 在实际开发中,...

    使用Java ThreadLocal.docx

    以下是一个完整的ThreadLocal示例,演示了如何在一个Runnable实例中使用ThreadLocal: ```java public class ThreadLocalExample { public static class MyRunnable implements Runnable { private ThreadLocal...

    ThreadLocal简单Demo

    4. **减少锁的使用**: 当多个线程需要共享同一资源,但每个线程只需要读取自己相关的数据时,`ThreadLocal`可以避免锁的使用,提升效率。 **注意事项** - 使用`ThreadLocal`后,应确保及时清理不再使用的变量,...

    Java中ThreadLocal的设计与使用

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,...总之,ThreadLocal是Java多线程编程中的一个强大工具,但使用时需谨慎,理解其工作原理和潜在风险,才能更好地利用它来解决实际问题。

    正确理解ThreadLocal.pdf

    ### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本...因此,在使用`ThreadLocal`时,应当充分理解其工作机制,合理规划其生命周期,并适时进行资源清理,以确保系统的稳定性和性能。

    ThreadLocal的几种误区

    因此,开发者在使用ThreadLocal时必须小心,避免在ThreadLocal中存储长期有效的数据,防止其他线程意外访问。 误区四:ThreadLocal可以随意多用 ThreadLocal虽然能提供方便的线程隔离,但过度依赖ThreadLocal可能...

    Spring事务处理-ThreadLocal的使用

    本篇文章将聚焦于Spring事务处理中ThreadLocal的使用,以及如何通过源码理解和应用这个工具。 首先,了解Spring事务管理的基本概念。在多线程环境中,事务管理是至关重要的,它负责确保一组数据库操作要么全部成功...

    ThreadLocal 内存泄露的实例分析1

    总结:`ThreadLocal` 是一个强大的工具,但在使用时必须谨慎,尤其是在多线程环境中,如 Tomcat 这样的 Web 容器。如果不正确地管理 `ThreadLocal` 的生命周期,可能导致类加载器级别的内存泄漏。理解 `ThreadLocal`...

    从ThreadLocal的使用到Spring的事务管理

    4. 不再使用时,调用remove方法清除线程局部变量,防止内存泄漏。 接下来,我们转向Spring框架的事务管理。Spring提供了声明式事务管理,开发者无需显式地编写事务管理代码,只需在配置文件或注解中声明事务属性,...

    JDK的ThreadLocal理解(一)使用和测试

    **标题:“JDK的ThreadLocal理解(一)使用和测试”** **正文:** ThreadLocal是Java中的一个非常重要的线程安全工具类,它在多线程...然而,使用时也要注意避免内存泄漏和过度依赖,合理规划其在系统架构中的位置。

    Quartz-ThreadLocal.rar

    这个压缩包 "Quartz-ThreadLocal.rar" 内含的学习资源很可能是关于如何在 Quartz 调度器中结合使用 ThreadLocal 的示例。 Quartz 的核心功能包括: 1. **作业与触发器**:在 Quartz 中,任务被称为“作业”(Job)...

Global site tag (gtag.js) - Google Analytics