ThreadLocal<T> 為每個線程提供獨立變量副本,解決多線程共享變量的線程安全問題。本文從原理、手寫簡易版、實戰模式、內存洩漏風險四個維度深度解析。
Thread 內部持有 ThreadLocalMap<ThreadLocal<?>, Object>,Key 為 ThreadLocal 實例(弱引用),Value 為線程局部變量public class SimpleThreadLocal {
private final Map<Thread, T> valueMap =
Collections.synchronizedMap(new HashMap<>());
public void set(T value) {
valueMap.put(Thread.currentThread(), value);
}
public T get() {
Thread t = Thread.currentThread();
T val = valueMap.get(t);
if (val == null && !valueMap.containsKey(t)) {
val = initialValue();
valueMap.put(t, val);
}
return val;
}
public void remove() { valueMap.remove(Thread.currentThread()); }
protected T initialValue() { return null; }
}
class Count {
private final ThreadLocal<Integer> count = ThreadLocal.withInitial(() -> 0);
public int increase() {
count.set(count.get() + 1);
return count.get();
}
}
// 4 線程並發,各自獨立計數 1→2→3
new Thread(() -> { for (int i=1;i<=3;i++) log(increase()); }).start();
輸出證明:每線程計數器互不干擾,均從 1 開始遞增。
SecurityContextHolder 底層即 ThreadLocalSimpleDateFormat 非線程安全,ThreadLocal 緩存實例remove(),推薦 try-finally 模式try {
threadLocal.set(value);
// 业务逻辑
} finally {
threadLocal.remove(); // 关键!
}
ThreadLocal.withInitial(Supplier):懶加載初始值,簡化匿名內部類InheritableThreadLocal:父線程值自動傳遞給子線程(注意:僅創建瞬間快照,後續修改不同步)