Threadlocal 源码分析与内存泄漏
2016-11-21 22:18
309 查看
参考链接
首先Map不存在于ThreadLocal,而是在Thread中Map
对象原理:
每个thread中都存在一个map,map的类型是ThreadLocal.ThreadLocalMap,Map中的key为一个threadlocal实例。
这个Map的确使用了弱引用,不过弱引用只是针对key,每个key都弱引用指向threadlocal,当threadlocal tl=null时,GC确实会回收tl实例对象。
但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用,Thread实例的Map带有value的强引用。只有当前thread结束以后,current thread就不会存在栈中,强引用断开,Current Thread, Map, value将全部被GC回收。
从中可以看出,弱引用只存在于key上,所以key会被回收。而value还存在着强引用,只有thead退出以后,thread中的map被销毁,value的强引用链条才会断掉。
所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。
Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal的get,set的时候都会清除线程Map里所有key为null的value。
ThreadLocal源码分析
public T get() { // 获取当前线程强引用 Thread t = Thread.currentThread(); // 获取ThreadLocalMap,是线程对象thread.threadLocals // 实际意义上ThreadLocal不存在Map,而是Thread类里存在Map ThreadLocalMap map = getMap(t); if (map != null) { // 获取其Entry ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
首先Map不存在于ThreadLocal,而是在Thread中Map
// 继承自弱引用 static class Entry extends WeakReference<ThreadLocal<?>> { // 这个value引用着Thread对应的副本对象 Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
对象原理:
每个thread中都存在一个map,map的类型是ThreadLocal.ThreadLocalMap,Map中的key为一个threadlocal实例。
这个Map的确使用了弱引用,不过弱引用只是针对key,每个key都弱引用指向threadlocal,当threadlocal tl=null时,GC确实会回收tl实例对象。
但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用,Thread实例的Map带有value的强引用。只有当前thread结束以后,current thread就不会存在栈中,强引用断开,Current Thread, Map, value将全部被GC回收。
从中可以看出,弱引用只存在于key上,所以key会被回收。而value还存在着强引用,只有thead退出以后,thread中的map被销毁,value的强引用链条才会断掉。
所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。
Java为了最小化减少内存泄露的可能性和影响,在ThreadLocal的get,set的时候都会清除线程Map里所有key为null的value。
降低内存泄露可能的写法
public class Test2 { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { ThreadLocal tl = new MyThreadLocal(); tl.set(new My50MB()); tl=null; System.out.println("Full GC"); System.gc(); } }).start(); System.gc(); Thread.sleep(1000); System.gc(); Thread.sleep(1000); System.gc(); Thread.sleep(1000); } }
相关文章推荐
- ThreadLocal源码及存在的内存泄漏分析
- ThreadLocal从源码分析总结到内存泄漏
- 并发编程(四):ThreadLocal从源码分析总结到内存泄漏
- ThreadLocal的研究_源码分析
- ThreadLocal(3)--源码分析
- folly源码分析(3)- ThreadLocalPtr
- ThreadLocal源码分析
- ThreadLocal源码分析
- 深入分析 ThreadLocal 内存泄漏问题
- ThreadLocal源码分析
- 深入分析 ThreadLocal 内存泄漏问题
- android-----ThreadLocal源码分析
- 深入分析 ThreadLocal 内存泄漏问题
- lesson1:threadlocal的使用demo及源码分析
- Spring源码分析【6】-ThreadLocal的使用和源码分析
- ThreadLocal的源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析和应用
- muduo源码分析:线程特定/私有数据类ThreadLocal
- 【惊天真相】ThreadLocal原理与源码分析