ThreadLocal简单了解

来源:互联网 发布:linux难吗 编辑:程序博客网 时间:2024/06/05 10:19
ThreadLocal,线程本地量。ThreadLocal为变量在每个线程都创建了一个副本,那么每个线程可以访问自己内部的
副本变量。

ThreadLocal的具体实现:

public T get(){}public void set(T valude){}public void remove(){}protected T initialValue(){}

get()方法是用来获取ThreadLocal在当前线程中保存的变量副本,set()用来设置当前线程中变量的副本,
remove()用来移除当前线程中变量的副本,initialValue()是一个protected方法,一般是用来在使用时进行重写
的,他是一个延迟加载的方法。
get方法的实现
第一句取得当前线程,然后根据getMap(t)方法获取到一个map,map的类型ThreadLocalMap。然后接着下面获取到
public T get(){Thread t=Thread.currentThread();ThreadLocalMap map=getMap(t);if(map!=null){ThreadLocalMap.Entry e=map.getEntry(this);if(e!=null){return (T)e.value;}}return setInitialValue();}
<key,value>键值对。
ThreadLocalMap getMap(Thread t){return t.threadLocals;}
在getMap中,是调用当前线程t,返回当前线程中的一个成员变量threadLocals
threadLocals是一个ThreadLocalMap,这个类型是ThreadLocal类的一个内部类。
static class ThreadLocalMap{static class Entry extends WeakRefence<ThreadLocal>{Object value;Entry(ThreadLocal k,Object v){super(k);value=v;}}}
ThreadLocalMap的Entry继承了WeakReference,并且使用ThreadLocal作为键值

private T setInitialValue(){T value=initialValue();Thread t=Thread.currentThread();ThreadLocalMap map=getMap(t);if(map!=null){map.set(this,value);}else{createMap(t,value);}return value;}

如果map不为空,就设置键值对,为空,在创建Map

void createMap(Thread t,T value){t.threadLocals=new ThreadLocalMap(this,firdtValue);}
ThreadLocal如何为每个线程创建变量的副本:
首先,在每个线程Thread内部有一个ThreadLocal。ThreadLocalMap类型的成员变量threadLocals,这个
threadLocals就是用来存储实际的变量副本的,键值为当前的ThreadLocal变量,Value为变量副本。
初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对
Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量
为value,存到threadLocals。
然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。

总结:
(1)实际的通过ThreadLocal创建的副本是存储在每个线程自己的ThreadLocals中的
(2)为何ThreadLocals的类型ThreadLoMap的键值为ThreadLocal对象,因为每个线程可有多个threadLocal变量
(3)在进行get之前,必须先set,否则汇报空指针异常。
0 0