兩者什么差異呢,咱們來看下源碼中的官方注釋?
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals =null;
/*
? ? * InheritableThreadLocal values pertaining to this thread. This map is
? ? * maintained by the InheritableThreadLocal class.
? ? */
? ? ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
都是Thread的變量,看著是不是幾乎一樣. 正如inheritableThreadLocals 變量比threadLocals名稱多的inheritable.
這里inheritableThreadLocals是可繼承的.
這是什么意思呢?:
1)我們知道threadLocals 是線程獨(dú)有的,也就是線程安全的.我們可將對線程安全 有要求的對象存在這里備用.
2)但是這里使用inheritableThreadLocals,a繼承b,則a線程內(nèi)部的inheritableThreadLocals會持有b中的值.
如何使用呢?
1)我們首先,針對threadLocals 和inheritableThreadLocals, 有兩個類:ThreadLocal 和InheritableThreadLocal
2)之前如何使用,將其替換就可以
Thread-A:
ThreadLocal threadLocal? = new new ThreadLocal<Object>(); //使用ThreadLocal的方式
Thread-B:
ThreadLocal threadLocal? = new new InheritableThreadLocal <Object>();//使用InheritableThreadLocal的方式
這個能力是如何實現(xiàn)的呢?
這個我們要看構(gòu)造Thread的時候做了什么
//Thread
private void init(ThreadGroup g, Runnable target, String name,
? ? ? ? ? ? ? ? ? ? ? long stackSize, AccessControlContext acc,
? ? ? ? ? ? ? ? ? ? ? boolean inheritThreadLocals) {
? ? ? ........
? ? ? ? if (inheritThreadLocals && parent.inheritableThreadLocals != null) //這里inheritThreadLocals 一直是true
? ? ? ? ? ? this.inheritableThreadLocals =
? ? ? ? ? ? ? ? ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); //這里是關(guān)鍵
? ? ? ......
}
ThreadLocal.createInheritedMap 又做了什么呢?
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++;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
我們看到所有的數(shù)值parentMap的值copy了一份到當(dāng)前的線程table中,我們?nèi)〉脮r候回去這里取:
private Entry getEntry(ThreadLocal<?> key) {
? ? ? ? ? ? int i = key.threadLocalHashCode & (table.length - 1);
? ? ? ? ? ? Entry e = table[i];
? ? ? ? ? ? if (e != null && e.get() == key)
? ? ? ? ? ? ? ? return e;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? return getEntryAfterMiss(key, i, e);
? ? ? ? }
其實用的時候,就當(dāng)做一個普通陌生的黑盒使用就好