引用结构

每个线程都有一个ThreadLocal.ThreadLocalMap类型的threadLocals属性, ThreadLocalMap中使用Entry来存储线程相关变量,Entrykey是对ThreadLocal的一个弱引用,value则是Object类型的线程变量。如下图:
threadlocal

内存泄漏

从引用结构上可以看到,若ThreadLocal没有被GC Roots强引用时,在垃圾回收后,ThreadLocal则会被回收, Entry的key无引用。若线程一直不退出,则value就一直不会被回收,造成内存泄漏。如下图:
threadlocal2

正确使用

内存泄漏的根本原因在于ThreadLocalMapThread的生命周期一样长,而不是因为弱引用导致内存泄漏的,需要在使用完调用remove方法手动清除数据,且ThreadLocal变量应该定义为static, 保证可以一直访问到,从而可以进行清除操作。