当一个子线程创建的时候,会把父线程的inheritableThreadLocals属性的值继承到自己的inheritableThreadLocals属性。
InheritableThreadLocal类的set()和get()方法都是用的父类即ThreadLocal的方法,而从ThreadLocal的源码中我们知道,ThreadLocal的get()、set()、remove()方法都会先调用getMap()方法,而InheritableThreadLocal重写了该方法,因此此时返回的ThreadLocalMap为inheritableThreadLocals
所以InheritableThreadLocal操作的属性为inheritableThreadLocals而不是threadLocals
xxxx
public class Thread {
/**
* 线程本地变量,线程本地变量在 ThreadLocal类 中维护。
* ThreadLocal values pertaining to this thread. This map is maintained by the ThreadLocal class.
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* 可继承的线程本地变量,可继承的线程本地变量在 InheritableThreadLocal类 中维护。
* InheritableThreadLocal values pertaining to this thread. This map is maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/**
* Returns a reference to the currently executing thread object.
*/
public static native java.lang.Thread currentThread();
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
// inheritThreadLocals 默认为true
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}
/**
* @param g
* @param target
* @param name
* @param stackSize
* @param acc
* @param inheritThreadLocals: if true, inherit initial values for inheritable thread-locals from the constructing thread
*
*/
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
java.lang.Thread parent = currentThread();
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
// 将父线程(parent)中 可继承的线程本地变量(inheritableThreadLocals) 继承过来。
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}
/**
* Factory method to create map of inherited thread locals. Designed to be called only from Thread constructor.
*
* @param parentMap the map associated with parent thread
* @return a map containing the parent's inheritable bindings
*/
static ThreadLocal.ThreadLocalMap createInheritedMap(ThreadLocal.ThreadLocalMap parentMap) {
return new ThreadLocal.ThreadLocalMap(parentMap);
}
}
xxxx
public class ThreadLocal<T> {
static class ThreadLocalMap {
private ThreadLocalMap.Entry[] table;
/**
* 创建一个只包含`可继承的线程本地变量`的ThreadLocalMap, 该方法只有在创建 可继承的线程本地变量map 时才会被调用。
* Construct a new map including all Inheritable ThreadLocals from given parent map. Called only by createInheritedMap.
*
* @param parentMap the map associated with parent thread.
*/
private ThreadLocalMap(ThreadLocal.ThreadLocalMap parentMap) {
ThreadLocal.ThreadLocalMap.Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
table = new ThreadLocal.ThreadLocalMap.Entry[len];
// 复制 parentMap 中的数据
for (int j = 0; j < len; j++) {
ThreadLocal.ThreadLocalMap.Entry e = parentTable[j];
if (e != null) {
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
if (key != null) {
/**
* 获取继承后的值。
* 说明:childValue方法定义了 可继承的线程本地变量 复制时的算法。InheritableThreadLocal类中childValue方法直接将父线程的变量返回,即直接继承父线程中的变量。
*/
Object value = key.childValue(e.value);
ThreadLocal.ThreadLocalMap.Entry c = new ThreadLocal.ThreadLocalMap.Entry(key, value);
int h = key.threadLocalHashCode & (len - 1);
while (table[h] != null)
h = nextIndex(h, len);
table[h] = c;
size++;
}
}
}
}
}
/**
* Method childValue is visibly defined in subclass InheritableThreadLocal,
* but is internally defined here for the sake of providing createInheritedMap factory method without needing to subclass the map class in InheritableThreadLocal.
* This technique is preferable to the alternative of embedding instanceof tests in methods.
*/
T childValue(T parentValue) {
throw new UnsupportedOperationException();
}
}
xxx
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(java.lang.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(java.lang.Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}