ThreadLocal可以保存一些变量仅供当前线程使用,其他线程不可见。 实际工作中可能会由于任务复杂,父线程创建几个子线程并发致性任务,那么父线程的本地变量如何传递到子线程呢? 答案是使用InheritableThreadLocal。
运行结果:
main = 12345 MyThread = 12345子线程中获取到了父线程的变量值。
如果将InheritableThreadLocal换为ThreadLocal,则子线程打印结果为MyThread = null,读者自行验证。
当我们在new Thread()时,会有从父线程拷贝线程本地变量到子线程的代码:
public Thread() { this(null, null, "Thread-" + nextThreadNum(), 0); } public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { this(group, target, name, stackSize, null, true); } private Thread(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { //省略... if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); //省略 }默认情况下,inheritThreadLocals值为true,parent.inheritableThreadLocals也不为空,所以会执行ThreadLocal.createInheritedMap方法。
static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); } private ThreadLocalMap(ThreadLocalMap parentMap) { Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshold(len); table = new Entry[len]; for (Entry e : parentTable) { 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++; } } } }这段代码比较简单,就是在创建子线程时逐个读取父线程的本地变量,赋值给子线程本地变量。