ThreadLocal是用来存放线程私有的变量的,
ThreadLocal主要是用ThreadLocalMap存放变量的,ThreadLocalMap有一个Entry[]数组存放,每个线程Thread都有两个ThreadLocal.ThreadLocalMap变量引用(threadLocals ,inheritableThreadLocals ),Entry是一个弱引用WeakReference<ThreadLocal<?>>。
强引用:就是创建一个对象,只要引用还指向堆中的对象,就不会被GC回收,内存不足直接抛出oom异常,也不会被回收。
弱引用:WeakReference修饰的,没有被强引用关联的时候,不管内存够不够,下次GC都会被回收。
两个强引用关联ThreadLocalMap中的entry:
1、全局变量或者静态变量修饰 如:private static ThreadLocal<Integer>
2、线程Thread引用。
内存泄漏原因:
1、被静态变量private static 修饰的threadLocal,这个是一个强引用,只要这个还存在,那ThreadLocalMap中的entry弱引用还存在,导致弱引用不能被gc回收,一直存放在ThreadLocalMap中,这就会导致内存泄漏。
2、线程强引用,线程Thread中有两个ThreadLocalMap变量,如果线程执行完run方法那还好,那就是不跟ThreadLocalMap强引用,entry弱引用也会被回收,但是如果是线程池的线程,线程不会销毁,那么线程和ThreadLocalMap还是强引用,那entry弱引用不会被回收导致内存泄漏。
即使静态变量threadLocal.remove()掉了把entry变成<null,value>也还是存放在ThreadLocalMap中,还是一直占据内存。
解决办法:
1、调用remove方法手动删除threadLocal的数据。
2、线程调用完把两个ThreadLocalMap置为null。
ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;