是什么
为 每个线程 提供独立变量副本,线程间互不干扰,避免共享变量同步。
private static final ThreadLocal<SimpleDateFormat> SDF = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
public String format(Date d) { return SDF.get().format(d);}典型场景:数据库 Connection(老代码)、用户上下文、SimpleDateFormat(现更推荐 DateTimeFormatter)、Spring 事务绑定。
原理(简述)
每个 Thread 持有 ThreadLocalMap(key 为 ThreadLocal 弱引用,value 为副本)。get() 从当前线程 map 取 value。
内存泄漏
ThreadLocal 被回收后,若线程长期存活(如线程池),map 中 entry 的 value 仍可能无法回收。
实践:用完 remove(),尤其线程池场景:
try { context.set(user); // business} finally { context.remove();}InheritableThreadLocal
子线程可继承父线程的值;线程池下仍可能不符合预期,异步传递上下文常用 TransmittableThreadLocal(TTL) 等方案。
与 synchronized 对比
ThreadLocal 空间换时间:每线程一份副本,无锁;适合「每线程独立状态」,不适合「必须全局一致」的数据。
一句话总结
ThreadLocal 解决「线程内私有状态」;线程池必须 finally 里 remove;父子线程传递慎用 InheritableThreadLocal。