一、复习
二、threadLocal不具有继承性
package com.ruigege.threadFoundation1;public class ThreadLocalExtend { public static ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main (String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run () { threadLocal.set("我是子线程的" ); System.out.println(threadLocal.get()); } }); thread.start(); try { Thread.sleep(1000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadLocal.get()); } }
7.1 从上面的两个ThreadLocal实例中可以看出,实例不具有继承性,也就是说主线程和子线程threadLocal变量值是不相等的,这也符合前面源码解析set方法。
二、如何让子线程能够访问到父线程的值呢?
我们还有一个成员变量没讲呢,那就是inheritableThreadLocal
我们先说一个类InheritableThreadLocal,这个类继承字ThreadLocal
public class InheritableThreadLocal <T > extends ThreadLocal <T > { protected T childValue (T parentValue) { return parentValue; } ThreadLocalMap getMap (Thread t) { return t.inheritableThreadLocals; } void createMap (Thread t,T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this ,firstValue); } }
后两个方法,可以看出来,其实就是把threadLocals成员变量换成了inheritaleThreadLocals。这样就完成替换了,下面看一下如何完成子线程调用父线程的变量
public Thread (Runnable target) { init(null ,target,"Thread-" +nextThreadNum(),0 ); }private void init (ThreadGroup g,Runnable target,String name,long stackSize,AccessControlContext acc) { .... Thread parent = currentThread(); .... if (parent.inheritableThreadLocal != null ){ this .inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals; this .stackSize = stackSize); tid = nextThreadID(); }static ThreadLocalMap createInheritedMap (Thread ThreadLocalMap map) { return new ThreadLocalMap(map); }
如上代码在创建线程的时候,在构造函数里面会调用init方法
进入到init方法里面,语句4就是获取了父线程,然后在后面的判断里,先判断一下父线程的inheritableThreadLocals是不是为空,如果不为空,那么我们赋值给子线程里面的inheritableThreadLocals,其中调用了一个函数,其实这个函数就是重新建立了一个ThreadLocalMap实例,接下来我们来观察一下源码
package com.ruigege.threadFoundation1;public class ThreadLocalMap { private Entry[] table; private T private ThreadLocalMap (ThreadLocalMap parentMap) { Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshole(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.chirld(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++; } } } } }
这段代码的基本思想就是复制父线程的inheritableThreadLocals变量到子线程中去。
三、并发和并行
并发指的是一段时间内多个线程同时执行,并且没有停止;
并行指的是单位时间内多个线程同时执行,并且没有停止;
并发强调的是一段时间,可能是由多个单位时间内组成的,并且可能一个单位时间只运行了一个线程。
四、源码:
所在包:com.ruigege.ThreadFoundation1
https://github.com/ruigege66/ConcurrentJava
欢迎关注微信公众号:傅里叶变换,个人账号,仅用于技术交流