`
22cgreen
  • 浏览: 55191 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

ThreadLocal研究

阅读更多
我在hibernate工厂类中看到了关于ThreadLocal的使用,threadLocal显然是类变量,全局的
是否这样表示不同的线程共享了threadLocal,事实上没错,多个线程取得到是同一样threadLocal
但是在不同的线程中使用threadLocal得到的变量不一样。那么什么是同一线程呢,我们可以这样理解
线程是主线程创建分支线程调用类执行完再返回主线程,那么这么这分支线程上所执行的所有对象的
方法实际上是同一个线程,除非中间使用多线程方法去创建其它分支线程。因此从创建分支线程
开始的那个方法一直执行到返回都是在同一线程中,其中引用的类,对象,方法都属性同一线程。

显示当前线程的方法为:
System.out.println(Thread.currentThread());

那么线程和对象方法有什么关系呢。当创建线程分支时,很显然就决定一个程序执行的线,
这个线的入口就是创建线程时给的方法的入口,方法一直向下执行,一部部的调用引用的其它类中的方法
如果碰到了实例化就加载类,如果类已加载过就直接实例化,如果static,在加载时就实际上分配了地址
直接跳到引用的地址继续执行,一直到执行完后返最后的代码。

在测试的过程中发现我们请求不同的页面时调用threadLocal.get()的结果一样的,这就有点奇怪了,
我测试的服务器是tomcat6.0+JDK1.6,为了模拟并发,我在其中一个线程中使用Thread.sleep(10000)
让线程等待10秒钟,结果发现再去请求另一个页面执行的线程并不一样,但是发现后面一个请求用的是前面
用过的一个线程,因此从这个线程得到的get()和前面执行完的那个线程一样的,只是和等待的那个线
程不一样。

因此有如下结论:
1)web请求的时分配的线程可能是以前用过的一个旧线程,线程保存着原来的一些值。
2)当并发产生时,会分配新的线程,新的线程和同时发生的别一个线程不是同一个线程,但是都有可能是以前的旧线程。
3)tomcat用的是线程池,有点类似于数据的连接池。
4)因此我们用完一个threadLocal应对其进行清除,以免下一个请求得到旧数据而产生影响。


在研究测试中发现。
1)Thread中有一个属性为:ThreadLocal.ThreadLocalMap threadLocals = null;
   也就是每一个线程都有这么一个ThreadLocalMap,这是线程所有固有的。当然如果没有使用到,这只是一个空属性。
  
2)而ThreadLoacl中的方法创建了一个ThreadLocal.ThreadLocalMap实例,相当于
   threadLocals = new ThreadLocalMap();
  
3)因此每一个线程都有一个ThreadLocalMap,只是没有使用时是空的罢了。

public T get()
  {
    Thread localThread = Thread.currentThread();
    ThreadLocalMap localThreadLocalMap = getMap(localThread);
    if (localThreadLocalMap != null)
      return ThreadLocalMap.access$000(localThreadLocalMap, this);
    Object localObject = initialValue();
    createMap(localThread, localObject);
    return localObject;
  }
 
public void set(T paramT)
  {
    Thread localThread = Thread.currentThread();
    ThreadLocalMap localThreadLocalMap = getMap(localThread);
    if (localThreadLocalMap != null)
      ThreadLocalMap.access$100(localThreadLocalMap, this, paramT);
    else
      createMap(localThread, paramT);
  }
 
   ThreadLocalMap getMap(Thread paramThread)
  {
    return paramThread.threadLocals;
  }
4)从上面ThreadLoacl原码可知getMap实际上就是得到指定线程的threadLocals值,当然threadLocals可能为null,而threadLocals就是一个ThreadLocal.ThreadLocalMap
5)我们看到上面的set方法也是一样的,调用了getMap方法。
6)Thread中的threadLocals 虽然没有说明作用域,但测试发现是protected类型,只有在子类或者同一个包中才能引用到。
因此我们只能通过和Thread的同一个包中的类来引用它。
 

------------------------------------------------------------------------------------
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
/**
* 得到session,此sessiond存有全属对象.
* @return //Session
*/
public static Session getSession()
{
Session re = threadLocal.get(); //这个地方不同的线程得到的值不一样的。
if(re==null) //此方法看线程变量中是否有值,如果有就用现存的值,没有就新实例化一个。
{
re = new Session();
threadLocal.set(re);
}
return re;
}

--------------------------------------------------------------
测试:1)看是否protected在同一个包中是否可引用。
测试结果:可以引用。

总结:private 只有在类内访问,就算是内部类也不能访问。
protected 类内,子类,同一个包中的类可以访问。
public 只要指明在那个包中,任何其它类都可能访问。
0
0
分享到:
评论
1 楼 shim 2010-11-21  
因此有如下结论: 
1)web请求的时分配的线程可能是以前用过的一个旧线程,线程保存着原来的一些值。 
2)当并发产生时,会分配新的线程,新的线程和同时发生的别一个线程不是同一个线程,但是都有可能是以前的旧线程。 
3)tomcat用的是线程池,有点类似于数据的连接池。


我的研究结果也是得出以上结论

但你说到
 
4)因此我们用完一个threadLocal应对其进行清除,以免下一个请求得到旧数据而产生影响。 

我觉得这在有些情况下没啥用,
比如有一个方法执行时间有些长,如需要30秒

第一个访问时从threadlocal中取得值,
在清除前第二个从threadlocal中取得值。

第一个访问执行完毕清除后,第二个访问还可能出现异常。

所以,可能并不是简单清除就可以解决问题

相关推荐

    入研究java.lang.ThreadLocal类.docx

    ### 知识点详解:Java.lang.ThreadLocal 类 #### 一、概述 **ThreadLocal** 并非线程的一种特殊实现形式,而是一种为每个线程提供独立副本的机制,通常被称为“线程局部变量”。这种机制使得每个线程都可以独立...

    高效Java后台程序缓存用户信息的研究.pdf

    在进行高效Java后台程序缓存用户信息的研究中,本文探讨了当前Java Web开发中常见的用户信息缓存实践,并对比了不同的缓存方式在效率和代码简洁性方面的优劣。在用户通过权限验证后,传统的做法是将用户信息保存在如...

    基于Java多线程同步的安全性研究.pdf

    "基于Java多线程同步的安全性研究" 本文主要研究了基于Java多线程同步的安全性问题,讨论了Java多线程同步机制的实现方法和安全性问题的解决方法。文章首先介绍了Java多线程同步的必要性和重要性,然后讨论了Java多...

    struts2源码研究

    - 如果`ThreadLocal`中没有`actionContext`,则基于`dispatcher`创建新的`ValueStack`,并将其放入`ContextMap`中。 - `CLEANUP_RECURSION_COUNTER`参数计数加1,并存入request中。 - 将`actionContext`存入`...

    基于全局储存的新思路 _ Tomcat的一种通用回显方法研究1

    为解决这一问题,文章引述了@kingkk师傅的研究,即通过反射修改Tomcat内部的控制变量,使请求处理过程中将Request和Response存储在ThreadLocal中,从而在反序列化时获取Response。 然而,这种方法受到Tomcat请求...

    java.lang研究

    《深入解析java.lang》 Java语言的核心库之一就是`java.lang`包,它包含了Java程序设计中最基础的类和接口,...通过深入研究`java.lang`,我们可以更好地理解Java的内在机制,并能更熟练地运用这些工具来解决问题。

    基于Hibernate的数据持久层关键技术的研究

    ### 基于Hibernate的数据持久层关键技术的研究 #### 一、引言 随着软件开发的不断进步和技术的发展,越来越多的企业级应用需要高效地管理和访问大量数据。为了更好地满足这一需求,许多开发团队选择了使用ORM...

    深入研究Servlet线程安全性问题

    3. **使用ThreadLocal**:ThreadLocal变量为每个线程提供独立的副本,避免了线程间的共享。 4. **避免共享状态**:设计无状态的Servlet,即不包含可变的实例变量,可以大大提高并发性能,因为无需担心线程安全。 5...

    Himo Zhu-京东IAST研究及实践.pdf

    1. **污点传播技术**:通过在请求中添加污点标记(如魔数),利用Tomcat线程机制和ThreadLocal,确保污点路径的唯一性,以追踪敏感数据在整个应用程序中的流动情况。 2. **栈签名算法**:在运行时,将栈信息转换为...

    Java系统中内存泄漏测试方法的研究

    这篇研究主要探讨了如何检测和分析Java应用中的内存泄漏问题。以下是对这个主题的详细阐述: 一、内存泄漏的理解 内存泄漏是指程序在申请内存后,无法释放已经不再使用的内存空间,一次小的内存泄漏可能不明显,但...

    Java并发编程实践-电子书-05章.pdf

    - **分析原因**:深入研究冲突发生的原因,如不恰当的锁使用、不充分的同步等。 - **修复方案**:根据分析结果,选择合适的同步机制或其他策略来解决冲突。 总之,通过理解和应用以上提到的各种技术手段,开发者...

    程序员面试中的多线程问题

    ### 知识点详解:Java多线程面试关键概念 #### 1....这些知识点涵盖了Java多线程面试中常见的几个核心概念,理解并掌握它们对于Java开发人员来说至关重要,尤其是在准备面试或深入研究并发编程时。

    Hibernate开发必备版

    ### Hibernate开发必备版知识点解析 #### 一、Hibernate概述 Hibernate是一种开源的对象关系映射(Object Relational Mapping,ORM)...对于更高级的应用场景,如事务管理、缓存策略等,还需要进一步深入学习和研究。

    lumaqq代码

    例如,QQ的即时通讯功能需要高效的并发处理,这离不开Java的并发库,如synchronized、volatile、ThreadLocal等关键字的运用。 其次,LumaQQ的网络通信机制是其关键部分。它使用了TCP/IP协议进行数据传输,这是所有...

    java研究源码-JavaResearch:在Java源代码上实现TestCase

    至于并发编程,Java提供了丰富的工具,如synchronized关键字、 volatile变量、ThreadLocal等,帮助开发者编写高效的多线程程序。 项目中可能还包括对Java反射API的探索。反射允许程序在运行时检查类、接口、字段和...

    struts2源代码分析

    深入研究这些类和方法,能让我们更好地定制和调试Struts2应用。 通过对Struts2的源代码进行分析,开发者可以更好地掌握其设计理念,解决性能问题,以及创建满足特定需求的扩展。这对于提升开发效率和应用质量至关...

    JDK10(JDK10底层C++源码及hotspot虚拟机源码)

    4. **ThreadLocal握手机制的改进**:为了解决内存泄漏问题,JDK10对`ThreadLocal`进行了优化,当线程结束时会自动清理相关的存储空间。 接下来,我们转向HotSpot虚拟机,它是Java运行时环境的核心组成部分。HotSpot...

    concurrent-1.3.4-sources.jar

    《并发编程库 concurrent-1.3.4-sources.jar 深度解析》 在Java编程领域,"concurrent"一词通常与多线程和...同时,这个库的源代码也是研究并发算法和数据结构的良好实例,有助于提升开发者在多线程环境下的编程能力。

Global site tag (gtag.js) - Google Analytics