一、復習
背景關系切換的時機:(1)執行緒中斷的時候;(2)執行緒使用完時間片處于就緒狀態的時候 形成死鎖的四個條件:(1)互斥條件;(2)請求并持有條件;(3)不可剝奪條件;(4)環路等待條件 根據作業系統原理,目前只能破除(2)和(4) 守護執行緒,格式:執行緒實體.setDaemon(true) ThreadLocal每一個執行緒都會copy一份
二、ThreadLocal實作原理
1.首先看一下Thread類
Thread類中有兩個成員變數 ThreadLocalMap threadLocals ThreadLocalMap inheritableThreadLocals
2.然后再看一下TheadLocal類中的成員方法
void set(T value) T get() ThreadLocalMap getMap(Thread t) void remove() T setInitialValue() void createMap(Thread t,T value)
3.ThreadLocalMap
可以理解為這是一個定制的HashMap 我們看到Thread里面的成員變數threadLocals,其實內部存盤的就是ThreadLocal的內容,ThreadLocal其實是一個工具殼,也就是說為什么會在每一個執行緒都有個ThreadLocal的副本,我們就解釋通了,因為它是Thread的自有成員變數 我們看一下ThreadLocal中set()方法的實作
ThreadLocalMap threadLocals;
ThreadLocalMap inheritableThreadLocals;
public void set(T value) {
Thread t = Thread.currentThread();//首先獲取行程本身
//首先獲取成員變數
ThreadLocalMap map = get(t);
if(map != null) {
map.set(this,value);
}else {
createMap(t,value);
}
}
ThreadLocalMap get(Thread t) {
return t.threadLocals;
}
void createMap(Thread t,T value) {
//key是this,這就說明,只能是這個ThreadLocal實體作為唯一key,這也保證了,所有執行緒的本地
//變數threadLocals的key是一致,保證了資料一致,如果用Thread實體做key,那就肯定不一樣了,
//因為每個Thread的實體不一樣,
threadLocals = new ThreadLocalMap(this,value);
}
總結:執行緒里面放一個map,然后ThreadLocal實體做key,set()方法里面放一個T value,那么就可以達到放副本了,用ThreadLocal實體做key,可以保證不同執行緒用的value一樣,
4.get()方法
public T get() {
Thread t = Thread.currentThread();//和set方法一樣先獲取本執行緒
ThreadLocalMap map = getMap(t);
if(map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if(e!=null) {
T result = (T)e.value();
return result;
}
}
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
//下面的代碼和set一樣,只不過我們只是提前設定了null為value
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map != null) {
map.set(this,value);
}else {
createMap(t,value);
}
return value;
}
protected T initialValue() {
return null;
}
}
5. remove方法
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if(m != null) {
m.remove(this);
}
}
總結:在每一個執行緒內部都有一個ThreadLocal變數,該變數的型別是HashMap,其中key就是我們的ThreadLocal實體,value就是呼叫set方法內部傳參的型別,每個執行緒的本地變數都會存在自己的threadLocal中,如果當前執行緒一直不消亡,那么這些變數就會一直存在,因此我們應該使用完執行緒之后,及時呼叫remove,洗掉這個多余的變數,否則會造成記憶體溢位,
三、原始碼:
所在包:com.ruigege.ThreadFoundation1 https://github.com/ruigege66/ConcurrentJavaCSDN:https://blog.csdn.net/weixin_44630050 博客園:https://www.cnblogs.com/ruigege0000/ 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流 
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/208614.html
標籤:其他
