`
22cgreen
  • 浏览: 53536 次
  • 性别: 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类.docx

    JAVA ThreadLocal类深入

    深入研究java.lang.ThreadLocal类。ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是 threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。

    Android 详解ThreadLocal及InheritableThreadLocal

    因为在android中经常用到handler来处理异步任务,通常用于接收消息,来操作UIThread,其中提到涉及到的looper对象就是保存在Threadlocal中的,因此研究下Threadlocal的源码。  分析都是基于android sdk 23 源码进行...

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

    解决Java多线程同步的方法是在需要同步的方法签名中加入synchronized关键字,...为解决多个线程对同一变量进行访问时可能发生的安全性问题,不仅可以采用同步机制,更可以通过JDK中加入的ThreadLocal来保证更好的并发性。

    JDK_seaswalker.tar.gz

    JDK源码阅读笔记 Condition CountDownLatch CyclicBarrier ReadWriteLock ReentrantLock ...ThreadLocal Reflection ScheduledThreadPool AsynchronousFileChannel BufferedInputStream Enum

    百度地图开发java源码-MD-Notes:计组、操作系统、数据结构、网络IO、Redis、MySQL、JVM等笔记

    希望踏实走技术路线,对业务、架构以及技术的底层知识做一些更深入的研究。 CSDN博客地址: Github 地址: **笔记持续更新中!喜欢的话,可以给个 star 噢 ~~** 面向后端开发攻城狮 各种基础知识,包括计组、计网、...

    java面试题以及技巧

    卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....

    java面试题目与技巧1

    卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....

    java面试题及技巧4

    卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....

    java面试题及技巧3

    卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....

    java面试题以及技巧6

    卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....

Global site tag (gtag.js) - Google Analytics