什么时候使用 InheritableThreadLocal
一、ThreadLocal 在父子線程傳遞的問題
public class InheritableThreadLocalDemo {// 全局變量 // static ThreadLocal<String> threadLocal = new ThreadLocal<>();static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {InheritableThreadLocalDemo.threadLocal.set("superWorld");new Service().call();}}).start();} }class Service {public void call() {System.out.println("Service:" + Thread.currentThread().getName() + " : " + InheritableThreadLocalDemo.threadLocal.get());//new Dao().call();new Thread(new Runnable() {@Overridepublic void run() {new Dao().call();}}).start();} }class Dao {public void call() {System.out.println("Dao:" + Thread.currentThread().getName() + " : " + InheritableThreadLocalDemo.threadLocal.get());}}?
?
二、InheritableThreadLocal 和?ThreadLocal 的區(qū)別
1. InheritableThreadLocal 實(shí)現(xiàn)
public class InheritableThreadLocal<T> extends ThreadLocal<T> {/*** Computes the child's initial value for this inheritable thread-local* variable as a function of the parent's value at the time the child* thread is created. This method is called from within the parent* thread before the child is started.* <p>* This method merely returns its input argument, and should be overridden* if a different behavior is desired.** @param parentValue the parent thread's value* @return the child thread's initial value*/protected T childValue(T parentValue) {return parentValue;}/*** Get the map associated with a ThreadLocal.** @param t the current thread*/ThreadLocalMap getMap(Thread t) {return t.inheritableThreadLocals;}/*** Create the map associated with a ThreadLocal.** @param t the current thread* @param firstValue value for the initial entry of the table.*/void createMap(Thread t, T firstValue) {t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);} }??
2. ThreadLocal 的getMap、createMap實(shí)現(xiàn)
/*** Get the map associated with a ThreadLocal. Overridden in* InheritableThreadLocal.** @param t the current thread* @return the map*/ThreadLocalMap getMap(Thread t) {return t.threadLocals;}/*** Create the map associated with a ThreadLocal. Overridden in* InheritableThreadLocal.** @param t the current thread* @param firstValue value for the initial entry of the map*/void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);}?
通過上面的代碼我們可以看到InheritableThreadLocal 重寫了childValue, getMap,createMap三個(gè)方法,
當(dāng)我們往里面set值的時(shí)候,值保存到了inheritableThreadLocals里面,而不是之前的threadLocals。
?
三、問題:為什么當(dāng)創(chuàng)建子線程時(shí),可以獲取到上個(gè)線程里的threadLocal中的值呢?
原因就是在新創(chuàng)建線程的時(shí)候,會(huì)把之前線程的inheritableThreadLocals賦值給新線程的inheritableThreadLocals,通過這種方式實(shí)現(xiàn)了數(shù)據(jù)的傳遞。
代碼關(guān)鍵點(diǎn):
1. Thread#init
if (parent.inheritableThreadLocals != null)this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);?
?
2.?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 (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.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++;}}}}?
總結(jié)
以上是生活随笔為你收集整理的什么时候使用 InheritableThreadLocal的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL replace into 用
- 下一篇: 何为TransmittableThrea