InheritableThreadLocal
InheritableThreadLocal
是如何在子线程中获取到父线程中的值的?
在线程new Thread
的时候,相关代码如下:
protected void init(......){
... ...
//如果父线程有可继承的线程本地变量,就将其复制到本线程的inheritableThreadLocals中
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
... ...
}
具体的复制逻辑为:
static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
return new ThreadLocalMap(parentMap);
}
//创建threadlocalmap(每个线程都维护一个ThreadLocalMap,key为ThreadLoca,value为具体的值)
private ThreadLocalMap(ThreadLocalMap parentMap) {
Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
table = new Entry[len];
for (int j = 0; j < len; j++) {
Entry e = parentTable[j];
if (e != null) {
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
if (key != null) {
Object value = key.childValue(e.value);
Entry c = new Entry(key, value);
int h = key.threadLocalHashCode & (len - 1);
while (table[h] != null)
h = nextIndex(h, len);
table[h] = c;
size++;
}
}
}
}
而具体InheritableThreadLocal的代码则非常简洁:
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
/**
* Computes the child's initial value for this inheritable thread-local
* variable as a function of the parent's value at the time the child
* thread is created. This method is called from within the parent
* thread before the child is started.
* <p>
* This method merely returns its input argument, and should be overridden
* if a different behavior is desired.
*
* @param parentValue the parent thread's value
* @return the child thread's initial value
*/
protected T childValue(T parentValue) {
return parentValue;
}
/**
* Get the map associated with a ThreadLocal.
*
* @param t the current thread
*/
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
/**
* Create the map associated with a ThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the table.
*/
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
因为父线程的值的copy逻辑都是在new子线程的时候,线程初始化时完成的。
整个逻辑为:
①Thread类内部维护一个inheritableThreadLocals变量
②某Thread初始化时,判断父线程中的inheritableThreadLocals中有无 线程本地变量,有则复制到该线程中的inheritableThreadLocals变量中。
③InheritableThreadLocal类重写了getMap方法,使其返回线程的inheritableThreadLocals变量,这样在get的时候,是从该key-value中获取。
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();
}
Last updated