pull/6/head
yuanguangxin 4 years ago
parent b875477d04
commit 66504d8071

@ -573,14 +573,12 @@ AQS有两个队列同步对列和条件队列。同步队列依赖一个双
ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时它所使用的所有 ThreadLocal 相对的实例副本都可被回收。
一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。而我们使用的 get()、set() 方法其实都是调用了这个ThreadLocalMap类对应的 get()、set() 方法。这个储值的Map并非ThreadLocal的成员变量而是java.lang.Thread 类的成员变量。ThreadLocalMap实例是作为java.lang.Thread的成员变量存储的每个线程有唯一的一个threadLocalMap。这个map以ThreadLocal对象为key”线程局部变量”为值所以一个线程下可以保存多个”线程局部变量”。对ThreadLocal的操作实际委托给当前Thread每个Thread都会有自己独立的ThreadLocalMap实例存储的仓库是Entry[] tableEntry的key为ThreadLocalvalue为存储内容因此在并发环境下对ThreadLocal的set或get不会有任何问题。在线程池的情况下处理完成后主动调用该业务treadLocal的remove()方法,将”线程局部变量”清空,避免本线程下次处理的时候依然存在旧数据。
一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。而我们使用的 get()、set() 方法其实都是调用了这个ThreadLocalMap类对应的 get()、set() 方法。这个储值的Map并非ThreadLocal的成员变量而是java.lang.Thread 类的成员变量。ThreadLocalMap实例是作为java.lang.Thread的成员变量存储的每个线程有唯一的一个threadLocalMap。这个map以ThreadLocal对象为key”线程局部变量”为值所以一个线程下可以保存多个”线程局部变量”。对ThreadLocal的操作实际委托给当前Thread每个Thread都会有自己独立的ThreadLocalMap实例存储的仓库是Entry[] tableEntry的key为ThreadLocalvalue为存储内容因此在并发环境下对ThreadLocal的set或get不会有任何问题。由于Tomcat线程池的原因我最初使用的”线程局部变量”保存的值在下一次请求依然存在同一个线程处理这样每次请求都是在本线程中取值。所以在线程池的情况下处理完成后主动调用该业务treadLocal的remove()方法,将”线程局部变量”清空,避免本线程下次处理的时候依然存在旧数据。
### ThreadLocal中的内存泄漏
### ThreadLocal为什么要使用弱引用和内存泄露问题
在ThreadLocal中内存泄漏是指ThreadLocalMap中的Entry中的key为null而value不为null。因为key为null导致value一直访问不到而根据可达性分析导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会被回收掉但是该value永远不能被访问到这样就存在了内存泄漏。如果 key 是强引用,那么发生 GC 时 ThreadLocalMap 还持有 ThreadLocal 的强引用,会导致 ThreadLocal 不会被回收,从而导致内存泄漏。弱引用 ThreadLocal 不会内存泄漏,对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,这算是最优的解决方案。
### ThreadLocal为什么要使用弱引用和内存泄露问题
Map中的key为一个threadlocal实例.如果使用强引用当ThreadLocal对象假设为ThreadLocal@123456的引用被回收了ThreadLocalMap本身依然还持有ThreadLocal@123456的强引用如果没有手动删除这个key则ThreadLocal@123456不会被回收所以只要当前线程不消亡ThreadLocalMap引用的那些对象就不会被回收可以认为这导致Entry内存泄漏。
如果使用弱引用那指向ThreadLocal@123456对象的引用就两个ThreadLocal强引用和ThreadLocalMap中Entry的弱引用。一旦ThreadLocal强引用被回收则指向ThreadLocal@123456的就只有弱引用了在下次gc的时候这个ThreadLocal@123456就会被回收。

Loading…
Cancel
Save