假设您要实现ThreadLocal.ThreadLocalMap,如何使它特定于线程? 当然,最简单的方法是在Thread类中创建一个非静态字段,我们将其称为2540580664605405410305。由于每个线程均由一个线程实例表示,因此每个线程中的254058066460541010306也将有所不同。 这也是Java的作用:
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap在这里是什么? 因为一个线程只有threadLocals,所以如果您简单地将threadLocals作为ThreadLocal(例如,将threadLocals定义为254058066460541010308),则一个特定线程只有254058066460541010309。 如果您想为一个线程使用多个ThreadLocal变量怎么办? 最简单的方法是将threadLocals设置为HashMap,每个条目的ThreadLocal313是ThreadLocal变量的名称,每个条目ThreadLocal315是ThreadLocal316变量的值。 有点困惑? 假设我们有两个线程t1和ThreadLocalMap,它们使用与25405806646221875875构造函数的参数相同的25405806646221875875实例,并且它们都有两个ThreadLocalMap变量,分别名为254058066462218752和HashMap和ThreadLocal。
t1.tlA
+-----+-------+
| Key | Value |
+-----+-------+
| tlA | 0 |
| tlB | 1 |
+-----+-------+
t2.tlB
+-----+-------+
| Key | Value |
+-----+-------+
| tlA | 2 |
| tlB | 3 |
+-----+-------+
请注意,这些值是由我组成的。
现在看来很完美。 但是ThreadLocalMap是什么? 为什么不只使用Entry class? 为了解决此问题,让我们看看通过2540580664622187587523类的WeakReference方法设置值时会发生什么:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap仅返回Entry class。由于WeakReference已初始化为ThreadLocalMap,因此我们首先输入HashMap:
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
它使用当前2540580664622187587521实例和要设置的值创建一个新的ThreadLocalMap实例。 让我们看看WeakReference是什么样的,它实际上是ThreadLocalMap类的一部分
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);
value = v;
}
}
...
/**
* Construct a new map initially containing (firstKey, firstValue).
* ThreadLocalMaps are constructed lazily, so we only create
* one when we have at least one entry to put in it.
*/
ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
...
}
ThreadLocalMap类的核心部分是Entry class,它扩展了2540580664622187587522。它确保如果当前线程退出,将自动进行垃圾回收。 这就是为什么它使用ThreadLocalMap而不是简单的HashMap的原因。它将当前的25405806646221875875和它的值作为2540580664622187187526类的参数传递,因此当我们想要获取该值时,可以从2540580664622187187527(该实例的一个实例)中获取它。 Entry类别:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
这就是整个图片: