`
小野bupt
  • 浏览: 14858 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

ThreadLocal-分析-总结

 
阅读更多

原文地址:http://www.iteye.com/topic/777716

ThreadLocal<T>类在Spring,Hibernate等框架中起到了很大的作用,对于其工作原理,很多网上的文章分析的不够彻底,甚至有些误解。

首先,为了解释ThreadLocal类的工作原理,必须同时介绍与其工作甚密的其他几个类(内部类)

1.ThreadLocalMap

2.Thread

可能有人会觉得Thread与ThreadLocal有什么关系,其实真正的奥秘就在Thread类中的一行:

Java代码收藏代码
  1. ThreadLocal.ThreadLocalMapthreadLocals=null;

其中ThreadLocalMap的定义是在ThreadLocal类中,真正的引用却是在Thread类中

那么ThreadLocalMap究竟是什么呢?

可以看到这个类应该是一个Map,JDK的解释是

写道
ThreadLocalMap is a customized hash map suitable only for maintaining thread local values

接下来的重点是ThreadLocalMap中用于存储数据的entry

Java代码收藏代码
  1. staticclassEntryextendsWeakReference<ThreadLocal>{
  2. /**ThevalueassociatedwiththisThreadLocal.*/
  3. Objectvalue;
  4. Entry(ThreadLocalk,Objectv){
  5. super(k);
  6. value=v;
  7. }
  8. }

从中我们可以发现这个Map的key是ThreadLocal变量,value为用户的值,并不是网上大多数的列子key是线程的名字或者标识

到这里,我们就可以理解ThreadLocal究竟是如何工作的了

1.Thread类中有一个成员变量叫做ThreadLocalMap,它是一个Map,他的Key是ThreadLocal类

2.每个线程拥有自己的申明为ThreadLocal类型的变量,所以这个类的名字叫'ThreadLocal':线程自己的(变量)

3.此变量生命周期是由该线程决定的,开始于第一次初始(get或者set方法)

4.由ThreadLocal的工作原理决定了:每个线程独自拥有一个变量,并非共享或者拷贝

Java代码收藏代码
  1. /**
  2. *@authormxdba
  3. *
  4. */
  5. publicclassThreadLocalSample{
  6. publicstaticvoidmain(String[]args){
  7. ThreadTesttest1=newThreadTest(10);
  8. ThreadTesttest2=newThreadTest(20);
  9. test1.start();
  10. test2.start();
  11. }
  12. }
  13. /**
  14. *此线程有两个ThreadLocal变量,但是由于ThreadLocal是延迟初始的,
  15. *所以在debug时可以看到线程名为“线程20”的线程的ThreadLocalMap中没有thLcal2这个entry
  16. *@authormxdba
  17. *
  18. */
  19. classThreadTestextendsThread{
  20. publicstaticThreadLocal<Integer>thLocal=newThreadLocal<Integer>();
  21. publicstaticThreadLocal<String>thLocal2=newThreadLocal<String>();
  22. publicIntegernum;
  23. publicThreadTest(Integernum){
  24. super("线程"+num);
  25. this.num=num;
  26. }
  27. @Override
  28. publicvoidrun(){
  29. Integern=thLocal.get();
  30. if(num!=20){
  31. Strings=thLocal2.get();
  32. }
  33. if(n==null){
  34. thLocal.set(num);
  35. }
  36. System.out.println(thLocal.get());
  37. }
  38. }

接下来分析一下源码,就更加清楚了

关键方法代码收藏代码
  1. /**
  2. *关键方法,返回当前Thread的ThreadLocalMap
  3. *[[[每个Thread返回各自的ThreadLocalMap,所以各个线程中的ThreadLocal均为独立的]]]
  4. */
  5. ThreadLocalMapgetMap(Threadt){
  6. returnt.threadLocals;
  7. }

Threadlocal的get方法代码收藏代码
  1. publicTget(){
  2. Threadt=Thread.currentThread();
  3. /**
  4. *得到当前线程的ThreadLocalMap
  5. */
  6. ThreadLocalMapmap=getMap(t);
  7. if(map!=null){
  8. /**
  9. *在此线程的ThreadLocalMap中查找key为当前ThreadLocal对象的entry
  10. */
  11. ThreadLocalMap.Entrye=map.getEntry(this);
  12. if(e!=null)
  13. return(T)e.value;
  14. }
  15. returnsetInitialValue();
  16. }

初始化方法代码收藏代码
  1. privateTsetInitialValue(){
  2. /**
  3. *默认返回null,这个方法为protected可以继承
  4. */
  5. Tvalue=initialValue();
  6. Threadt=Thread.currentThread();
  7. ThreadLocalMapmap=getMap(t);
  8. if(map!=null)
  9. map.set(this,value);
  10. else
  11. /**
  12. *初次创建
  13. */
  14. createMap(t,value);
  15. returnvalue;
  16. }

Java代码收藏代码
  1. /**
  2. *给当前thread初始ThreadlocalMap
  3. */
  4. voidcreateMap(Threadt,TfirstValue){
  5. t.threadLocals=newThreadLocalMap(this,firstValue);
  6. }

通过上边的分析,我们发现,ThreadLocal类的使用虽然是用来解决多线程的问题的,但是还是有很明显的针对性

1.最明显的,ThreadLoacl变量的活动范围为某线程,并且我的理解是该线程“专有的,独自霸占”,对该变量的所有操作均有该线程完成!也就是说,ThreadLocal不是用来解决共享,竞争问题的。典型的应用莫过于Spring,Hibernate等框架中对于多线程的处理了

Java代码收藏代码
  1. privatestaticfinalThreadLocalthreadSession=newThreadLocal();
  2. publicstaticSessiongetSession()throwsInfrastructureException{
  3. Sessions=(Session)threadSession.get();
  4. try{
  5. if(s==null){
  6. s=getSessionFactory().openSession();
  7. threadSession.set(s);
  8. }
  9. }catch(HibernateExceptionex){
  10. thrownewInfrastructureException(ex);
  11. }
  12. returns;
  13. }

这段代码,每个线程有自己的ThreadLocalMap,每个ThreadLocalMap中根据需要初始加载threadSession,这样的好处就是介于singleton与prototype之间,应用singleton无法解决线程,应用prototype开销又太大,有了ThreadLocal之后就好了,对于需要线程“霸占”的变量用ThreadLocal,而该类实例的方法均可以共享。

2.关于内存泄漏:

虽然ThreadLocalMap已经使用了weakReference,但是还是建议能够显示的使用remove方法。

分享到:
评论

相关推荐

    ThreadLocal 内存泄露的实例分析1

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

    正确理解ThreadLocal.pdf

    3. **日志记录**:在多线程环境中,`ThreadLocal`可以用于维护每个线程的日志上下文,如线程ID、用户名等,便于日志信息的记录和分析。 4. **性能优化**:在某些计算密集型应用中,`ThreadLocal`可以用于缓存线程...

    理解threadlocal

    通过以上分析,我们可以看到`ThreadLocal`为多线程环境下的编程提供了一种简洁优雅的解决方案。它不仅能够避免复杂的同步问题,还能有效地管理线程间的变量隔离。理解`ThreadLocal`的工作原理及其使用方法,可以帮助...

    简单分析Java线程编程中ThreadLocal类的使用共

    总结来说,Java线程编程中的ThreadLocal类提供了一种高效、便捷的方式来实现线程间的隔离数据,但同时也需要开发者注意其潜在的内存泄漏风险。正确理解和使用ThreadLocal,能够帮助我们编写出更加健壮、高效的并发...

    Java并发编程学习之ThreadLocal源码详析

    ThreadLocal的实现原理可以总结为:每个线程都有一个自己的ThreadLocalMap,用于存放线程的本地变量;ThreadLocal的set、get、remove方法都是基于ThreadLocalMap的操作。 ThreadLocal的优点是可以解决多线程访问...

    入研究java.lang.ThreadLocal类.docx

    **分析**: - 使用 `ThreadLocal&lt;Session&gt;` 确保每个线程都有独立的 Session 实例。 - 通过 `initialValue()` 方法初始化每个线程的 Session。 - `currentSession()` 方法确保每次调用都能获取到当前线程的 Session ...

    一次使用Eclipse Memory Analyzer分析Tomcat内存溢出

    #### 四、总结 通过本次使用 Eclipse Memory Analyzer (MAT) 分析 Tomcat 内存溢出的过程,我们可以得出以下结论: - 内存管理对于 Java 应用程序至关重要。 - 遇到内存溢出或泄露问题时,MAT 是一款非常强大的...

    mat java 分析 文件 dump

    进一步分析显示,“java.lang.ThreadLocal$ThreadLocalMap$Entry[]”可能是问题的根源。在这种情况下,MAT提供了指向具体问题的线索,即通过查看Leak Suspects Problem Suspect1 Details页面来获取更多信息。这里...

    并发编程总结.xmind

    java并发编程总结,包括多线程安全机制分析总结,Unsafe源码分析总结,并发工具类总结,ThreadLocal原理和使用,Fork/Join框架使用总结,同步容器和并发容器源码分析

    2019年一线互联网公司Java高级面试题总结

    - 使用工具进行性能分析,如JVisualVM、JProfiler等。 - **效果**: - 提升应用程序运行速度和响应性,减少内存占用。 #### 6. Class.forName与Class.getClassLoader - **Class.forName**: - 加载指定类,并返回...

    互联网创意产品众筹平台

    │ 7-登录功能异步开发总结 │ 8-MD5概述5 _* g* f: Y1 v* o4 H │ 9-MD5-工具类1 H6 x* t" K- z* B │ 10-登录功能-MD5密码加密' F4 `+ B( c' b5 I' ?7 a │ 11-注销功能9 z3 d8 y4 A0 l: p* n* @ │ 12-附录3.页面...

    java源码总结-Java-Concurrent-Programming:java并发编程学习总结源码部分

    本项目“Java-Concurrent-Programming”是一个基于《Java并发编程艺术》这本书的学习总结,通过源码分析来深入理解并发编程的核心概念。 在Java中,线程是并发的基础,`Thread`类提供了创建和管理线程的基本功能。...

    Hessian源码分析和Hack.doc

    总结,Hessian作为高效的RPC框架,虽然没有内置获取客户端信息的功能,但通过分析其源码并适当扩展,我们能够实现这一需求。需要注意的是,直接修改开源库的源码可能带来维护上的困扰,因此在可行的情况下,推荐使用...

    Java互联网架构多线程并发编程原理及实战 视频教程 下载4.zip

    Java互联网架构多线程并发编程原理及实战 ...11-1 数据同步接口--需求分析.mp4 11-2 中间表设计.mp4 11-3 基础环境搭建.mp4 11-4 生产者代码实现.mp4 11-5 消费者编码实现.mp4 12-1 课程总结.mp4 笔记课件.zip

    Java互联网架构多线程并发编程原理及实战 视频教程 下载2.zip

    Java互联网架构多线程并发编程原理及实战 ...11-1 数据同步接口--需求分析.mp4 11-2 中间表设计.mp4 11-3 基础环境搭建.mp4 11-4 生产者代码实现.mp4 11-5 消费者编码实现.mp4 12-1 课程总结.mp4 笔记课件.zip

    Java互联网架构多线程并发编程原理及实战 视频教程 下载3.zip

    Java互联网架构多线程并发编程原理及实战 ...11-1 数据同步接口--需求分析.mp4 11-2 中间表设计.mp4 11-3 基础环境搭建.mp4 11-4 生产者代码实现.mp4 11-5 消费者编码实现.mp4 12-1 课程总结.mp4 笔记课件.zip

    Java互联网架构多线程并发编程原理及实战 视频教程 下载.zip

    Java互联网架构多线程并发编程原理及实战 ...11-1 数据同步接口--需求分析.mp4 11-2 中间表设计.mp4 11-3 基础环境搭建.mp4 11-4 生产者代码实现.mp4 11-5 消费者编码实现.mp4 12-1 课程总结.mp4 笔记课件.zip

    Java互联网架构多线程并发编程原理及实战 视频教程 下载1.zip

    Java互联网架构多线程并发编程原理及实战 ...11-1 数据同步接口--需求分析.mp4 11-2 中间表设计.mp4 11-3 基础环境搭建.mp4 11-4 生产者代码实现.mp4 11-5 消费者编码实现.mp4 12-1 课程总结.mp4 笔记课件.zip

    ikm_java_8.pdf

    通过以上分析,我们了解了Java 8中关于多线程安全的一些技巧、JavaScript表单验证的基本原理、如何在Servlet中读取初始化参数以及Swing组件类型的区别。这些知识点对于开发高质量的Java应用程序至关重要。

    笔试面试题国内知名公司

    - 接口与抽象类的使用场景分析 - 继承与多态的深入探讨 4. **Java并发编程** - 线程的创建与同步,如synchronized、volatile关键字 - Lock接口和ReentrantLock的使用 - ThreadLocal原理及应用场景 - 并发工具...

Global site tag (gtag.js) - Google Analytics