ThreadLocal 用来存储线程私有数据,数据存放在ThreadLocalMap中。ThreadLocalMap内部维护Entry[]数组。Entry继承WeakReference<ThreadLocal<?>>,Entry 以 ThreadLocal 为 key,保存对应的 value。key 是弱引用, 外部threadLocal=null之后,GC 可以回收 ThreadLocal 对象,避免了 key 对象的内存泄漏 。value 是强引用 。在线程池场景下,核心线程长期存活不会销毁,如果没有手动清理,value 存在强引用链就会发生内存泄漏。因此使用完成必须调用remove()防止内存泄漏。普通线程执行完毕后线程会被回收,ThreadLocalMap、Entry、value 随之回收,不会产生内存泄漏。
调用 set ()/get () 时底层会自动清理 key 为 null 的 Entry;但如果后续不再调用 get、set 方法,底层无法自动清理,依旧会发生 value 内存泄漏,所以最佳实践是手动调用 remove ()。