ThreadLocal解读

适用场景

  线程级别的变量,适用于变量在线程间隔离而在方法或者类间共享的场景。

基础原理

ThreadLocal解读
强引用链路:Thread –> ThreadLocalMap –> Entry –> Object。

内存泄露

问题: 如上图所示,ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用引用他,那么系统gc的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value,永远无法回收,造成内存泄露。
JDK解决方案:

  1. ThreadLocal变量定义成private static的。这样的话ThreadLocal的生命周期就更长,由于一直存在ThreadLocal的强引用,所以ThreadLocal也就不会被回收,也就能保证任何时候都能根据ThreadLocal的弱引用访问到Entry的value值。
  2. 调用set/get方法时将key为null的value删除。缺点是需要通过调用set/get方法触发,如果不主动调用就存在内存泄露的风险。

性能问题

  当发生哈希冲突时,会线性遍历数组,如下图所示,不适合ThreadLocal众多,对性能要求高的场景,参见Netty的FastThreadLocal。
ThreadLocal解读
ThreadLocal解读

线程池与ThreadLocal

  线程池中的线程是重复使用的,即一次使用完后,会被重新放回线程池,如果ThreadLocal线程变量保存的信息只是针对一次请求的,放回线程池之前需要清空这些Threadlocal变量的值(或者取得线程之后,首先清空这些Threadlocal变量的值)。

参考:https://www.cnblogs.com/xzwblog/p/7227509.html