这三种的关系因为大量的内部类的关系,第一次看的时候仍是有点绕的,感受你是老子的孙子,又是老子的老子。我仍是建议你先抛开内部类的关系,把每个类看成普通类来看到,理解每個类的职责,最后再把内部类放进去考虑这样设计的目的。这里也给你们一个启示,面对复杂的事情的时候,咱们须要跳出来,先把问题简单化,大方向把握了,再进一步去细化每个功能点和设计的艺术。java
接下来咱们看下面一张图面试
看到各类内部类是否是有点晕,感受你是老子的孙子,又是老子的老子,为何不独立ThreadLocalMap 出来呢?其实这里涉及到内部类起到封装的做用。来,咱们看看源码的解析小程序
/** * ThreadLocalMap is a customized hash map suitable only for * maintaining thread local values. No operations are exported * outside of the ThreadLocal class. The class is package private to * allow declaration of fields in class Thread. To help deal with * very large and long-lived usages, the hash table entries use * WeakReferences for keys. However, since reference queues are not * used, stale entries are guaranteed to be removed only when * the table starts running out of space. */
static class ThreadLocalMap {
//这里省略其余属性和方法
}
复制代码
主要是说明ThreadLocalMap 是一个线程本地的值,它全部的方法都是private 的,也就意味着除了ThreadLocal 这个类,其余类是不能操做ThreadLocalMap 中的任何方法的,这样就能够对其余类是透明的。同时这个类的权限是包级别的,也就意味着只有同一个包下面的类才能引用ThreadLocalMap 这个类,这也是Thread 为何能够引用ThreadLocalMap 的缘由,由于他们在同一个包下面。数组
虽然Thread 能够引用ThreadLocalMap,可是不能调用任何ThreadLocalMap 中的方法。这也就是咱们平时都是经过ThreadLocal 来获取值和设置值,看下如下代码ide
public class Test {
public static void main(String[] args) {
ThreadLocal<String> local = new ThreadLocal<>();
local.set("hello word");
System.out.println(local.get());
}
}
复制代码
但咱们调用ThreadLocal 的get 方法的时候,其实咱们最后是经过调用ThreadLdocalMap 来获取值的ui
public T get() {
//这里经过获取当前的线程
Thread t = Thread.currentThread();
//经过线程来获取ThreadLocalMap ,还记得咱们上面说的Thread 里面有一个ThreadLocalMap 属性吗?就是这里用上了
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();
}
复制代码
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
复制代码
到这里,读者应该大概明白了,其实ThreadLdocalMap 对使用者来讲是透明的,能够看成空气,咱们一值使用的都是ThreadLocal,这样的设计在使用的时候就显得简单,而后封装性又特别好。this
在第一次调用ThreadLocal set() 方法的时候开始绑定的,来咱们看下set 方法的源码spa
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
//第一次的时候进来这里,由于ThreadLocalMap 还没和Thread 绑定
createMap(t, value);
}
//这个时候开始建立一个新的ThreadLocalMap 赋值给Thread 进行绑定
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
复制代码
若是你以为这篇内容对你挺有启发,我想邀请你帮我2个小忙:线程