1

1. 什么是 ThreadLocal?

ThreadLocal 可以简单理解为“线程的本地变量容器”。
打个比方:每个线程就像一个人,ThreadLocal 就像每个人身上带的专属小口袋。

  • 线程往口袋里存数据,只有自己能访问,其他线程的“口袋”内容独立,互不干扰。
  • 例如:线程 A 存用户 A 的信息,线程 B 存用户 B 的信息,彼此无法获取对方的数据,避免多线程数据混乱。

2. 使用 ThreadLocal 时需要注意什么?

  1. 及时清理数据
    线程使用完后需调用 remove() 方法清理数据。若线程被线程池复用,未清理的残留数据可能导致后续业务逻辑出错。
  2. 避免内存泄漏

    • ThreadLocalMap 的 Entry 中,key(ThreadLocal 实例)是弱引用,若 ThreadLocal 被回收,key 会变为 null,但 value 仍被强引用。
    • 若线程长期存活(如线程池核心线程),value 会持续占用内存,导致泄漏。需通过 remove() 主动清除 value。
  3. 不滥用
    适合存储线程私有、多方法共享的数据(如用户上下文、事务信息),避免用它传递所有数据,否则会增加代码耦合性和调试难度。
  4. 父子线程数据传递
    普通 ThreadLocal 的数据无法被子线程获取,若需共享可使用 InheritableThreadLocal,但线程池场景下子线程可能复用,需谨慎处理。

3. ThreadLocal 常见面试题

  1. ThreadLocal 的作用是什么?
    为每个线程提供独立的变量副本,实现线程内数据隔离,避免多线程共享变量的同步问题。
  2. ThreadLocal 的实现原理是什么?

    • 每个线程(Thread)内部有 ThreadLocalMap 对象(ThreadLocal 的静态内部类)。
    • ThreadLocal 实例作为 key,存储的值作为 value 存入该 map。
    • get() 方法:获取当前线程的 ThreadLocalMap,以当前 ThreadLocal 为 key 取 value;set() 方法:往 map 中存值。
  3. 为什么 ThreadLocal 可能导致内存泄漏?如何避免?

    • 原因:ThreadLocalMap 的 Entry 中 key 是弱引用,key 回收后 value 仍被强引用,若线程长期存活则导致内存泄漏。
    • 避免:使用后调用 remove() 清除 value。
  4. ThreadLocal 和 synchronized 的区别?

    • ThreadLocal:为每个线程提供独立副本,避免竞争,本质是“空间换时间”。
    • synchronized:通过加锁让线程排队访问共享资源,本质是“时间换空间”。
  5. InheritableThreadLocal 是什么?和 ThreadLocal 有何区别?

    • InheritableThreadLocal 是 ThreadLocal 的子类,支持父子线程数据传递(父线程变量自动传给子线程)。
    • 普通 ThreadLocal 中,子线程无法获取父线程的变量;线程池场景下子线程可能复用,需谨慎处理。
  6. Spring 中哪里用到了 ThreadLocal?
    事务管理(如 TransactionSynchronizationManager)、请求上下文(如 RequestContextHolder)等,用于存储当前线程的事务信息、请求信息,保证线程内数据一致性。

今夜有点儿凉
46 声望8 粉丝

今夜有点儿凉,乌云遮住了月亮。


引用和评论

0 条评论