回答
ThreadLocal
是 Java 并发中一个非常重要的类,是用来解决Java多线程程序中并发问题的一种途径。它为每个使用该变量的线程提供一个独立的变量副本,因此每个线程都可以独立地改变自己的副本,而不会影响其他线程中的副本,线程之间的竞态条件被彻底消除了。
ThreadLocal
的核心原理是为每个线程提供一个独立的变量副本,从而实现线程之间的数据隔离。这是通过在每个线程内部维护一个名为 ThreadLocalMap
的映射来实现的,其中键是 ThreadLocal
对象,值是线程特有的变量副本。这样,每个线程只能访问和修改自己的变量副本,而不会干扰到其他线程。为了避免内存泄漏,ThreadLocalMap
使用弱引用作为键,所以我们在使用的时候需要手动清理 ThreadLocal
变量。
ThreadLocal 实现原理详解
Thread、ThreadLocal、ThreadLocalMap 三者之间的关系
要掌握 ThreadLocal
的核心原理,第一要务就是要厘清楚 Thread、ThreadLocal、ThreadLocalMap 三者之间的关系。
Thread 里面有一个 ThreadLocalMap 的成员变量 threadLocals:
ThreadLocal.ThreadLocalMap threadLocals = null;
从这里可以看出,每个线程都有自己的 ThreadLocalMap。ThreadLocalMap 是 ThreadLocal 的静态内部类:
public class ThreadLocal<T> {
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
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<k,v>
,每个 Entry 的 key 是ThreadLocal 实例的弱引用,value 则线程的专属变量。关系如下:
我们看下 ThreadLocal
的 get()
源码:
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();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
操作顺序是这样的:ThreadLocalMap map = thread.threadLocals
—> return map.getEntry(threadLocal)
。这里我们可以再次进一步理解他们的关系:
set()
的源码:
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 map = thread.threadLocals
—> map.set(threadLocal, value)
,再次精进他们的关系:
源码及使用方法大明哥就不阐述了,ThreadLocal 的源码很简单,重点在于理解 Thread、ThreadLocal、ThreadLocalMap 之间的关系。