继前面《ThreadLocal源码阅读》知道ThreadLocal原理是获取当前线程Thread的一个Map,通过Entry封装 key为ThreadLocal对象自身 value为我们的值。但是ThreadLocal本身不是子线程共享的。InheritableThreadLocal就是为了解决子线程共享问题
我们知道线程变量都是通过Thread对象的threadLocals存储,其实除了这个线程对象还提供子线程共享的Map inheritableThreadLocals,创建子线程此变量会默认复制一份父线程此Map,注:是复制并不是继承 所以还是线程安全的,子线程set值并不会影响父线程或者其他子线程的值
/* 当前线程共享 子线程并不能共享 * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * * 创建线程时子线程会复制一份 */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/** * 复制父类ThreadLocalMap的时候调用 原路复制不做任何处理 * @param parentValue * @return */ protected T childValue(T parentValue) { return parentValue; } /** * 重写getMap获取线程对象的inheritableThreadLocals 后续复制也是复制此对象 具体可以看ThreadLocal源码 * * @param t the current thread */ ThreadLocal.ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } /** * * @param t the current thread * @param firstValue value for the initial entry of the table. */ void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue); }
//<2>构造函数实现复制 Thread thread=new Thread(new Runnable() { @Override public void run() { } });
public Thread(Runnable target) { //<3> init(null, target, "Thread-" + nextThreadNum(), 0); }
private void init(ThreadGroup g, Runnable target, String name, long stackSize) { //<4>最后一个参数为true表示复制父线程 init(g, target, name, stackSize, null, true); }
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { if (name == null) { throw new NullPointerException("name cannot be null"); } this.name = name; //获得父线程也是创建子线程的线程 Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); if (g == null) { if (security != null) { g = security.getThreadGroup(); } if (g == null) { g = parent.getThreadGroup(); } } g.checkAccess(); if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext(); this.target = target; setPriority(priority); //inheritThreadLocals为true 同时inheritableThreadLocals不为空则复制父线程的 if (inheritThreadLocals && parent.inheritableThreadLocals != null) //<5>复制父线程的inheritableThreadLocals this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }
static ThreadLocal.ThreadLocalMap createInheritedMap(ThreadLocal.ThreadLocalMap parentMap) { //<6>复制 return new ThreadLocal.ThreadLocalMap(parentMap); }
private ThreadLocalMap(ThreadLocal.ThreadLocalMap parentMap) { ThreadLocal.ThreadLocalMap.Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshold(len); table = new ThreadLocal.ThreadLocalMap.Entry[len]; //遍历inheritableThreadLocals的值 for (int j = 0; j < len; j++) { ThreadLocal.ThreadLocalMap.Entry e = parentTable[j]; if (e != null) { //这里获取到的是InheritableThreadLocal ThreadLocal<Object> key = (ThreadLocal<Object>) e.get(); if (key != null) { //调用childValue 被重写 Object value = key.childValue(e.value); //用新的Entry封装保存到当前map 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++; } } } }