原文地址:http://www.iteye.com/topic/777716
ThreadLocal<T>类在Spring,Hibernate等框架中起到了很大的作用,对于其工作原理,很多网上的文章分析的不够彻底,甚至有些误解。
首先,为了解释ThreadLocal类的工作原理,必须同时介绍与其工作甚密的其他几个类(内部类)
1.ThreadLocalMap
2.Thread
可能有人会觉得Thread与ThreadLocal有什么关系,其实真正的奥秘就在Thread类中的一行:
-
ThreadLocal.ThreadLocalMapthreadLocals=null;
其中ThreadLocalMap的定义是在ThreadLocal类中,真正的引用却是在Thread类中
那么ThreadLocalMap究竟是什么呢?
可以看到这个类应该是一个Map,JDK的解释是
写道
ThreadLocalMap is a customized hash map suitable only for maintaining thread local values
接下来的重点是ThreadLocalMap中用于存储数据的entry
-
staticclassEntryextendsWeakReference<ThreadLocal>{
-
-
Objectvalue;
-
-
Entry(ThreadLocalk,Objectv){
-
super(k);
-
value=v;
-
}
-
}
从中我们可以发现这个Map的key是ThreadLocal变量,value为用户的值,并不是网上大多数的列子key是线程的名字或者标识
到这里,我们就可以理解ThreadLocal究竟是如何工作的了
1.Thread类中有一个成员变量叫做ThreadLocalMap,它是一个Map,他的Key是ThreadLocal类
2.每个线程拥有自己的申明为ThreadLocal类型的变量,所以这个类的名字叫'ThreadLocal':线程自己的(变量)
3.此变量生命周期是由该线程决定的,开始于第一次初始(get或者set方法)
4.由ThreadLocal的工作原理决定了:每个线程独自拥有一个变量,并非共享或者拷贝
-
-
-
-
-
publicclassThreadLocalSample{
-
-
publicstaticvoidmain(String[]args){
-
ThreadTesttest1=newThreadTest(10);
-
ThreadTesttest2=newThreadTest(20);
-
test1.start();
-
test2.start();
-
}
-
-
}
-
-
-
-
-
-
-
-
classThreadTestextendsThread{
-
-
publicstaticThreadLocal<Integer>thLocal=newThreadLocal<Integer>();
-
publicstaticThreadLocal<String>thLocal2=newThreadLocal<String>();
-
-
publicIntegernum;
-
-
-
-
publicThreadTest(Integernum){
-
super("线程"+num);
-
this.num=num;
-
}
-
-
@Override
-
publicvoidrun(){
-
Integern=thLocal.get();
-
if(num!=20){
-
Strings=thLocal2.get();
-
}
-
-
if(n==null){
-
thLocal.set(num);
-
}
-
System.out.println(thLocal.get());
-
}
-
-
}
接下来分析一下源码,就更加清楚了
-
/**
-
*关键方法,返回当前Thread的ThreadLocalMap
-
*[[[每个Thread返回各自的ThreadLocalMap,所以各个线程中的ThreadLocal均为独立的]]]
-
*/
-
ThreadLocalMapgetMap(Threadt){
-
returnt.threadLocals;
-
}
-
publicTget(){
-
Threadt=Thread.currentThread();
-
/**
-
*得到当前线程的ThreadLocalMap
-
*/
-
ThreadLocalMapmap=getMap(t);
-
if(map!=null){
-
/**
-
*在此线程的ThreadLocalMap中查找key为当前ThreadLocal对象的entry
-
*/
-
ThreadLocalMap.Entrye=map.getEntry(this);
-
if(e!=null)
-
return(T)e.value;
-
}
-
returnsetInitialValue();
-
}
-
privateTsetInitialValue(){
-
/**
-
*默认返回null,这个方法为protected可以继承
-
*/
-
Tvalue=initialValue();
-
Threadt=Thread.currentThread();
-
ThreadLocalMapmap=getMap(t);
-
if(map!=null)
-
map.set(this,value);
-
else
-
/**
-
*初次创建
-
*/
-
createMap(t,value);
-
returnvalue;
-
}
-
-
-
-
voidcreateMap(Threadt,TfirstValue){
-
t.threadLocals=newThreadLocalMap(this,firstValue);
-
}
通过上边的分析,我们发现,ThreadLocal类的使用虽然是用来解决多线程的问题的,但是还是有很明显的针对性
1.最明显的,ThreadLoacl变量的活动范围为某线程,并且我的理解是该线程“专有的,独自霸占”,对该变量的所有操作均有该线程完成!也就是说,ThreadLocal不是用来解决共享,竞争问题的。典型的应用莫过于Spring,Hibernate等框架中对于多线程的处理了
-
privatestaticfinalThreadLocalthreadSession=newThreadLocal();
-
-
publicstaticSessiongetSession()throwsInfrastructureException{
-
Sessions=(Session)threadSession.get();
-
try{
-
if(s==null){
-
s=getSessionFactory().openSession();
-
threadSession.set(s);
-
}
-
}catch(HibernateExceptionex){
-
thrownewInfrastructureException(ex);
-
}
-
returns;
-
}
这段代码,每个线程有自己的ThreadLocalMap,每个ThreadLocalMap中根据需要初始加载threadSession,这样的好处就是介于singleton与prototype之间,应用singleton无法解决线程,应用prototype开销又太大,有了ThreadLocal之后就好了,对于需要线程“霸占”的变量用ThreadLocal,而该类实例的方法均可以共享。
2.关于内存泄漏:
虽然ThreadLocalMap已经使用了weakReference,但是还是建议能够显示的使用remove方法。
分享到:
相关推荐
java并发编程总结,包括多线程安全机制分析总结,Unsafe源码分析总结,并发工具类总结,ThreadLocal原理和使用,Fork/Join框架使用总结,同步容器和并发容器源码分析
│ 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.页面...
高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4 高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4 高并发编程第三阶段13讲 一个JNI程序的编写,通过...
高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4 高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4 高并发编程第三阶段13讲 一个JNI程序的编写,通过...
│ │ │ Java程序员认证模拟题及详细分析.doc │ │ │ question.rar │ │ │ test4.doc │ │ │ 模拟题.rar │ │ │ 经典的104-147模拟题.rar │ │ │ │ │ ├─035 │ │ │ 2003.10.5.15.51.43.TestKing%...
│ │ │ Java程序员认证模拟题及详细分析.doc │ │ │ question.rar │ │ │ test4.doc │ │ │ 模拟题.rar │ │ │ 经典的104-147模拟题.rar │ │ │ │ │ ├─035 │ │ │ 2003.10.5.15.51.43.TestKing%...
│ │ │ Java程序员认证模拟题及详细分析.doc │ │ │ question.rar │ │ │ test4.doc │ │ │ 模拟题.rar │ │ │ 经典的104-147模拟题.rar │ │ │ │ │ ├─035 │ │ │ 2003.10.5.15.51.43.TestKing%...
│ │ │ Java程序员认证模拟题及详细分析.doc │ │ │ question.rar │ │ │ test4.doc │ │ │ 模拟题.rar │ │ │ 经典的104-147模拟题.rar │ │ │ │ │ ├─035 │ │ │ 2003.10.5.15.51.43.TestKing%...
│ │ │ Java程序员认证模拟题及详细分析.doc │ │ │ question.rar │ │ │ test4.doc │ │ │ 模拟题.rar │ │ │ 经典的104-147模拟题.rar │ │ │ │ │ ├─035 │ │ │ 2003.10.5.15.51.43.TestKing%...
ThreadLocal 线程池 MySql redis 系统设计 TCP/IP 分布式事务 消息队列 源码 数据库分库分表 自己总结 Java JVM 内存模型 垃圾回收 如何设计一个可达性分析系统 类加载机制 双亲委派机制 SPI 并发 synchronized 偏向...
深入分析java单例模式什么是单例模式单例模式的常见写法一、饿汉式单例优点缺点示例二、懒汉式单例示例1(普通写法)示例2(synchronized写法)示例3(DCL写法)示例4(内部类写法)三、注册式单例示例1(容器式)示例2(枚举式...