ThreadLocal 名稱易誤以為是「Thread 的親戚」,實則意為**線程本地變量**——每個線程擁有獨立副本,將共享變量轉化為線程隔離的私有變量,從根本上消除併發衝突。
ThreadLocalMap),鍵為 ThreadLocal 實例,值為線程副本。get() 時若無副本,調用 initialValue() 初始化並綁定當前線程。典型例子:DAO 持有 Connection。多線程共用 DAO 實例時,Connection 的連接/關閉狀態極易衝突。用 ThreadLocal 給每個線程分配獨立 Connection,線程間互不干擾,性能大增。
ThreadLocal:多佔內存(每線程一份副本),**絕不等待**。synchronized:省內存,**接受等待**。// 版本 1:無同步,共享 num → 結果混亂
class OperationSample {
private int num;
public void printAndIncrementNum() {
for (int i=0; i<2; i++) {
System.out.println(Thread.currentThread().getName() + "[id=" + num + "]");
num += 10;
}
}
}
// 版本 2:ThreadLocal 隔離,每線程初始 0 → 每線程輸出 0, 10
class OperationSample2 {
private static ThreadLocal<Integer> threadArg = new ThreadLocal<Integer>() {
protected Integer initialValue() { return 0; }
};
public void printAndIncrementNum() {
for (int i=0; i<2; i++) {
int num = threadArg.get();
threadArg.set(num + 10);
System.out.println(Thread.currentThread().getName() + "[id=" + num + "]");
}
}
}
// 版本 3:配合 AtomicInteger 分配唯一初始值 → 線程首次輸出 0~4,第二次 +10
class OperationSample3 {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
private static ThreadLocal<Integer> threadArg = new ThreadLocal<Integer>() {
protected Integer initialValue() { return uniqueId.getAndIncrement(); }
};
// printAndIncrementNum 同版本 2
}
ThreadLocal 管理事務、Session 等非線程安全狀態。synchronized。remove() 避免內存洩漏(線程池場景尤其重要)。