threadLocal的应用主要是对一个线程内的变量进行传递不会创建对象,比如在全局日志里的应用,数据库连接池的应用也是。但是threadLocal也存在一个问题。
第一:因为在实际中的使用的时候,我们使用的tomcat的线程池时候,如果使用完不删除threadLocal里面数据,会导致数据可能在下次请求时,被其他线程可见。
第二:ThreadLocal底层结构,每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例.
private void set(ThreadLocal<?> key, Object value) {} 这是ThreadLocalMap,key是ThreadLocal的ThreadLocal里面有个原子类,但是是用static修饰的,也就是说在类加载时,被赋值。
ThreadLocal导致内存泄露的根源
首先需要明确一点:ThreadLocal本身的设计是不会导致内存泄露的,原因更多是使用不当导致的!
ThreadLocalMap对象被Thread对象所持有,当线程退出时,Thread类执行清理操作,比如清理ThreadLocalMap;否则该ThreadLocalMap对象的引用并不会被回收。
根源:由于Entry的key弱引用特性(见注意),当每次GC时JVM会主动将无用的弱引用回收掉,因此当ThreadLocal外部没有强引用依赖时,就会被自动回收,这样就可能造成当ThreadLocal被回收时,相当于将Map中的key设置为null,但问题是该key对应的entry和value并不会主动被GC回收,
当Entry和value未被主动回收时,除非当前线程死亡,否则线程对于Entry的强引用会一直存在,从而导致内存泄露
建议: 当希望回收对象,最好使用ThreadLocal.remove()方法将该变量主动移除,告知JVM执行GC回收
注意: ThreadLocal本身不是弱引用的,Entry继承了WeakReference,同时Entry又将自身的key封装成弱引用,所有真正的弱引用是Entry的key,只不过恰好Entry的key是ThreadLocal。
直接用这个创建,最后在删除即可。
原博文:https://blog.csdn.net/qq_32296307/article/details/117408759