跳转至

ThreadLocal 原理和内存泄漏

一、原理

每个 Thread 对象里有一个 ThreadLocalMap。

class Thread {
    ThreadLocalMap threadLocals;
}

ThreadLocalMap 的 key 是 ThreadLocal(弱引用),value 是值。

二、为什么会泄漏

key 是弱引用

GC 时 key 被回收,变成 null。

value 是强引用

value 不会被回收。

如果线程一直活着(线程池),这些 null key 的 value 永远不会清,泄漏。

三、怎么避免

用完调用 remove():

try {
    threadLocal.set(value);
    // 业务
} finally {
    threadLocal.remove();
}

四、应用

  • Spring 事务连接绑定。
  • 用户上下文。
  • 日期格式化。

五、InheritableThreadLocal

子线程能拿到父线程的值。

六、线程池注意

线程池线程复用,一定要 remove,否则数据串了。

一句话

ThreadLocal = Thread 里的 Map,用完必须 remove。