1、 在线程内部有一个ThreadLocalMap属性;
/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; |
2、 ThreadLocal内主要的属性成员和方法成员:
主要的方法成员:
public T get();//返回当前线程内ThreadLocal变量的副本,可能需要先初始化;
public void set(T value);//为当前线程内ThreadLocal变量的副本赋值,可能需要先初始化;
public void remove();//从当前线程的ThreadLocalMap属性的Entry数组中移除该ThreadLocal对应的Entry;
ThreadLocalMap getMap(Thread t);//返回线程t的ThreadLocalMap属性;
private T setInitialValue();//初始化;
void createMap(Thread t, T firstValue);//为线程t的ThreadLocalMap进行初始化。
主要的数据成员:
private final int threadLocalHashCode;//用来保存当前ThreadLocal的哈希码;
private static AtomicInteger nextHashCode;//用来计算ThreadLocal的哈希码,确保每个ThreadLocal的实例的哈希码均不相同;
private static final int HASH_INCREMENT;//通过原子性的给nextHashCode增加该值确保ThreadLocal哈希值的唯一性。
主要内部类ThreadLocalMap的相关信息(很像是HashMap的简化版本):
主要的数据成员:
private static final int INITIAL_CAPACITY;//初始容量,必须是2的幂;
private Entry[] table;//Entry数组,需要时进行扩容,长度必须是2的幂;
private int size;//table中Entry的数量;
private int threshold;//当容量达到threshold的3/4时需要进行扩容,值为table长度的2/3。
主要的方法成员:
private void setThreshold(int len);//用来设置shreshold的值;
private static int nextIndex(int i, int len);//用来对i进行循环加1,当达到len时,重置为0;
private static int prevIndex(int I, int len);//用来对i进行循环减1,当达到0时,重置为len-1;
private Entry getEntry(ThreadLocal> key);//在table表中查找key对应的Entry,通过key的哈希码&(table.length-1)得到table中的索引i,如果table[i]==key,返回Entry,否则继续寻找下一个,找不到返回null;
private void set(ThreadLocal> key, Object value);//更新或者插入(key,value);
private void remove(ThreadLocal> key);//移除key对应的Entry;
private void rehash();//当size的值达到threshold的3/4时,进行扩容;
private void resize();//创建一个新的数组,容量为之前的2倍,对旧数组中每一个不为空的Entry,重新计算在新数组中的位置,并防止到新数组中,更新table及相应的变量。
内部类:Entry继承自WeakReference
3、 ThreadLocal中方法的具体实现:
思路:首先通过Thread.currentThread()获得当前运行的线程t,然后通过t. threadLocals获得线程的ThreadLocalMap成员map,之后再调用ThreadLocalMap中的相应的方法更新或者查询map;
public T get();
功能:返回当前线程内ThreadLocal变量的副本,如果map为空的话,先对map进行初始化
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } |
private T setInitialValue();
功能:初始化当前线程的ThreadLocalMap成员
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; } |
void createMap(Thread t, T firstValue);
功能:具体的初始化函数
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); } |
public void set(T value);
功能:将<当前ThreadLocal, value>添加到当前线程的ThreadLocalMap中,如果ThreadLocalMap没有初始化的话,先进行初始化
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } |
public void remove();
功能:从当前线程的ThreadLocalMap中移除当前ThreadLocal对应的Entry
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); } |
ThreadLocalMap getMap(Thread t);
功能:返回线程t的ThreadLocalMap
ThreadLocalMap getMap(Thread t) { return t.threadLocals; } |
4、 思路梳理
Thread中有一个ThreadLocalMap成员属性threadLocals,ThreadLocal中有一个内部类ThreadLocalMap,以及成员属性和操作ThreadLocalMap的成员方法;
这些成员方法的工作流程为:
先获取当前运行的线程t,通过当前线程t获得线程的数据成员threadLocals,然后通过threadLocals调用ThreadLocalMap中的相应的方法完成对threadLocals的更新。
5、 结论
当线程调用ThreadLocal的相应方法操作变量时,实际上操作的是线程自身的局部变量,因此是线程封闭的,消除了竞争条件。