一、復習
ThreadLocal的set\get等方法
二、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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(threadLocal.get());
}
}

從上面的兩個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);//this是一個InheritableThreadLocal實體,
}
}
后兩個方法,可以看出來,其實就是把threadLocals成員變數換成了inheritaleThreadLocals,這樣就完成替換了,下面看一下如何完成子執行緒呼叫父執行緒的變數 先來看看Thread原始碼
public Thread(Runnable target){
init(null,target,"Thread-"+nextThreadNum(),0);
}
private void init(ThreadGroup g,Runnable target,String name,long stackSize,AccessControlContext acc){
....
//獲取當前執行緒(4)
Thread parent = currentThread();
....
//如果父執行緒的inheritableThreadLocal變數不為null
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) {
//下面這幾行就是為了獲取Entry實力的key和value并且生成一個新的Entry實體
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>)e.get();
if(key != null) {
Object value = key.chirld(e.value);//回傳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/ConcurrentJavaCSDN:https://blog.csdn.net/weixin_44630050 博客園:https://www.cnblogs.com/ruigege0000/ 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流 
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/212680.html
標籤:Java
上一篇:ArrayList原始碼分析
