zoukankan      html  css  js  c++  java
  • ThreadLocal 在web环境下使用的边界问题

    ThreadLocal 相关分析,请查看http://wangxinchun.iteye.com/blog/1884228 
    另外一个必须要提的点是: 
    ThreadLocal在线程池环境下的使用。 
    比如tomcat 提供的web http请求,一般都有线程池对请求做处理。 

    这种情况下要注意,并非每次web请求时候程序运行的ThreadLocal都是唯一的,ThreadLocal的生命周期不等于一次Request的生命周期,ThreadLocal与线程对象紧密绑定的,由于Tomcat使用了线程池,线程是可能存在复用情况,这时的ThreadLocal 的使用要谨慎使用。 

    web请求下 的ThreadLocal  使用要保证:请求进来的时候set,请求回去的时候remove。只有这样才能保证请求内的ThreadLocal  是唯一的。 这个特性在深刻的提醒我们:一次http请求和tomcat启动处理业务的线程并非一一对应的,而是通过一个线程池进行调度。 
    错误的使用案例: 

    Java代码  收藏代码
    1. @Controller  
    2. public class ThreadLocalController {  
    3.     private static final ThreadLocal<Integer> id = new ThreadLocal<Integer>();  
    4.   
    5.     @ResponseBody  
    6.     @RequestMapping("/threadLocalTest")  
    7.     public Map<String, Object> threadLocalTest() {  
    8.         Integer myId = id.get();  
    9.         if (myId == null) {  
    10.             id.set(1);  
    11.         } else {  
    12.             id.set(id.get() + 1);  
    13.         }  
    14.         System.out.println(id.get());  
    15.         Map<String, Object> retMap = new LinkedHashMap<String, Object>();  
    16. retMap.put("id", id.get());  
    17.         return retMap;  
    18.     }  
    19. }  


    以上代码运行的时候会发现,命令行打印的id 是不确定的,这时因为tomcat本身对请求做线程池缓存业务处理线程导致的。 

    正确的使用案例: 

    Java代码  收藏代码
    1. @Controller  
    2. public class ThreadLocalController {  
    3.   
    4.     private static final ThreadLocal<Integer> id = new ThreadLocal<Integer>();  
    5.   
    6.     @ResponseBody  
    7.     @RequestMapping("/threadLocalTest")  
    8.     public Map<String, Object> threadLocalTest() {  
    9.         Integer myId = id.get();  
    10.         if (myId == null) {  
    11.             id.set(1);  
    12.         } else {  
    13.             id.set(id.get() + 1);  
    14.         }  
    15.         System.out.println(id.get());  
    16.         Map<String, Object> retMap = new LinkedHashMap<String, Object>();  
    17.         retMap.put("id", id.get());  
    18.         id.remove();  
    19.         return retMap;  
    20.     }  
    21. }  


    以上代码每次输出的都是1,注意id.remove() 方法的调用,在每次请求结束的时候remove对象。 

    更多的情况下,做为系统级别的,可以在filter下做ThreadLocal对象set 和 remove 操作!

  • 相关阅读:
    php逻辑操作符中&和&&的异同
    Web性能压力测试工具之WebBench详解
    Entity Framework加载相关实体——延迟加载Lazy Loading、贪婪加载Eager Loading、显示加载Explicit Loading
    EF中的贪婪加载和延迟加载(懒加载)
    WCF中的数据契约(DataContract)
    无废话WCF入门教程六[一个简单的Demo]
    无废话WCF入门教程五[WCF的通信模式]
    无废话WCF入门教程四[WCF的配置文件]
    无废话WCF入门教程三[WCF的宿主]
    无废话WCF入门教程二[WCF应用的通信过程]
  • 原文地址:https://www.cnblogs.com/qiumingcheng/p/4894564.html
Copyright © 2011-2022 走看看