ThreadLocal内存泄漏
简述
ThreadLocal是什么,是java中用于实现线程内变量的工具类。允许每个线程都拥有自己的副本,从而实现线程隔离,解决多线程的共享对象的线程安全问题。
ThreadLocal的使用
1 | public static ThreadLocal<String> localVariable = new ThreadLocal<>(); // 新建 |
详述
实现原理
ThreadLocal的底层实现是一个特殊的map,可以理解往ThreadLocal设置一个xxx值,就是往这个特殊的map中设置一个key为当前线程,value为xxx的值。由于他的key只能为当前线程,所以在某个线程中set和get都不会影响其他线程,从而到达线程安全。下图的ThreadLocalMap就是拿个特殊的map。
总体来说,java在运行的过程中会维护一个ThreadLocalMap,这个ThreadLocalMap的key为各个线程,value为各个线程想存放的东西,可以是String,可以是map,List等等。当时由于key为各个线程,所有每个线程只能由一个Entry ,也就是一个键值对(key-value),当然线程也可以不设置不存放。
内存泄露
都知道ThreadLocal会内存泄漏,那么这个内存泄漏又是怎么回事。
都知道在java虚拟机中栈是私有的,而堆是共享的,所以ThreadLocalMap是存放在堆中的,而栈中存的只是一个引用,如下图。
由于Entry extends WeakReference<ThreadLocal<?>>,所以可以看到,Entry中的key指向ThreadLocal是弱引用,也就是线程执行完之后,这个ThreadLocal就会被释放清理掉,但是由于ThreadLocalMap指向Entry是强引用,所以Entry不会被释放清理,如果这Entry一直不被清理释放,那么ThreadLocalMap的内存占用就会越来越大,以至于内存也漏。
所以为了防止这种问题的发生,在用完时,记得释放清理。
1 | try { |