ThreadLocal 提供執行緒區域變數:每個執行緒擁有獨立副本,互不干擾。「以空間換時間」,避免同步開銷。
每個 Thread 內部持有 ThreadLocalMap:
// 簡化版 ThreadLocalMap
static class ThreadLocalMap {
static class Entry extends WeakReference> {
Object value;
Entry(ThreadLocal> k, Object v) { super(k); value = v; }
}
private Entry[] table;
// get/set 操作當前執行緒的 map
}
ThreadLocal 作為 key,值存儲於當前執行緒的 map 中。
public class RequestContext {
private static final ThreadLocal holder = new ThreadLocal<>();
public static void set(Request req) { holder.set(req); }
public static Request get() { return holder.get(); }
public static void clear() { holder.remove(); } // 防洩漏
}
// 過濾器中
RequestContext.set(new Request(httpRequest));
try {
// 業務邏輯可隨處取得 Request
Request req = RequestContext.get();
} finally {
RequestContext.clear();
}
| 場景 | 說明 |
|---|---|
| 資料庫連線管理 | 每執行緒獨享 Connection,避免併發衝突 |
| Session/請求上下文 | Web 框架傳遞請求相關資料 (用戶、權限、追蹤 ID) |
| 日期格式化 | SimpleDateFormat 非執行緒安全,ThreadLocal 複用實例 |
| 事務管理 | Spring @Transactional 執行緒綁定事務狀態 |
| 序號生成器 | 每執行緒獨立序號,無需同步 |
子執行緒可繼承父執行緒的值:
InheritableThreadLocal itl = new InheritableThreadLocal<>();
itl.set("parent-value");
// 新執行緒自動獲得副本
// 結構化並發專用,自動生命週期管理
ScopedValue SV = ScopedValue.newInstance();
ScopedValue.runWhere(SV, request, () -> {
// 子執行緒自動可見,結束自動清理
});