ThreadLoacl 能做到每个线程独立的原因 看一下set方法就一目了然了 获取当前线程 获取这个线程的本地变量,最终无论干什么事情,都是ThreadLocalMap来做,所以很好理解,还有一个 如果不对他进行remove的话 ,可能会有问题,这里存疑 如果只是线程本地成员变量 线程销毁变会被回收 一定要remove吗
这里有需要回收 似乎ThreadLocalMap是一个map但ThreadLocalMap并不是一个java.util.Map接口的实现,但是从Entry的实现和整个ThreadLocalMap的实现来看却实现了一个Map的功能,并且从具体的方法的实现上来看,整个ThreadLocalMap实现了一个HashMap的功能,对比HashMap的实现就能看出。
ThreadLocal<T>
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 Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
ThreadLocalMap 获取值的方法
1、首先获取当前线程;
2、根据当前线程获取一个Map;
3、如果获取的Map不为空,则在Map中以ThreadLocal的引用作为key来在Map中获取对应的value e,否则转到5;
4、如果e不为null,则返回e.value,否则转到5;
5、Map为空或者e为空,则通过initialValue函数获取初始值value,然后用ThreadLocal的引用和value作为firstKey和firstValue创建一个新的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();
}
InheritableThreadLocal 继承于ThreadLocal 所以也就是个Map 然后里面
InheritableThreadLocal<T>
//在Thread中ThreadLocal inheritableThreadLocals 都是并列的 意义就是一个是不可以传递的一个是可以传递的
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
最最关键的是如何实现继承 线程有他的init 初始化方法 在这个方法中判断了是不是存在可继承的ThreadLocal变量
关键代码如下
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
Thread parent = currentThread(); parent就是当前的线程
this自己就是要生成的线程 一个线程初始化完成 才可以算完成的线程
inheritThreadLocals是个boolean变量,是这个Init方法的形参,这个Init方法被三处调用,只有下面的时候才会是false,所以才如果不是下面的方法都会默认继承
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}