ThreadLocal会为每个线程分配一个变量副本,在Thread类中通过ThreadLocalMap进行保存,key为ThreadLocal对象,value为设置的值,其中key为弱引用。
接下来要从以下2个方面进行讨论:
1、ThreadLocal是局部变量还是全局变量
2、程序中是否使用了线程池
首先来讨论2,如果程序未使用线程池,那么线程会在执行完后自动销毁,即内部的成员ThreadLocalMap也会被回收,此时无论1中ThreadLocal是局部变量还是全局变量都不会有影响。
如果2中使用了线程池:当1中ThreadLocal是局部变量时,那么在方法执行完之后,ThreadLocal对象将不会有强引用,在进行GC的时候,ThreadLocalMap的key指向的ThreadLocal将被回收,但是value得不到释放,所以这种情况需要执行ThreadLocal.remove()手动释放。
当1中ThreadLocal是全局变量时(被static修饰),那么ThreadLocal的生命周期可以看做和程序的生命周期一致,即只要程序不崩溃或者停止,ThreadLocal将一直持有强引用(一般在项目里ThreadLocal使用的是这种方式),那么在进行GC的时候,ThreadLocalMap的key永远无法回收,这种情况也需要执行ThreadLocal.remove()手动释放。
综上所述,情况可以分为三类:
1、上述2中未使用线程池
2、上述2中使用线程池,1中ThreadLocal是局部变量
3、上述2中使用线程池,1中ThreadLocal是全局变量
对于情况1来说,使用完ThreadLocal后,可以不使用ThreadLocal.remove()手动释放。
对于情况2、3来说,使用完ThreadLocal后,必须使用ThreadLocal.remove()进行手动释放。
但你无法确定以后项目里会不会使用线程池?如果以后使用了,而未执行ThreadLocal.remove(),那将是一个隐患,所以建议情况1也调用remove手动释放。
结论:如果你能保证项目一定不会用到线程池,可以不用ThreadLocal.remove()手动释放,否则必须要手动释放。
关于ThreadLocalMap的key为何要设置为弱引用,从上述的情况2也能看出,当线程要运行很长时间时(线程池),通过GC可以释放key所占用的内存。
标签:释放,完后,remove,ThreadLocal,线程,key,使用 From: https://www.cnblogs.com/kjxcom/p/18317185