ThreadLocal源码分析
来源:互联网 发布:工程造价需要什么软件 编辑:程序博客网 时间:2024/05/29 09:50
源码比较简单,但是里面有很多优化的地方。
TheadLocal.get()的时候实际上拿到当前线程的threadLocalMap,以theadLocal为key,取value的过程。
源码为证:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }但是ThreadLocalMap是一个静态内部类。其中的entry是一个weakReference<ThreadLocal>,其中ThreadLocal是key。所以当GC发生时,无论是minor GC还是major GC,如果threadLocal没有外部强引用,那么threadlocal会被GC掉,但是value是entry的强引用,不会被GC,这样的entry被称为stale Entry。这样存在的一个问题就是在适当的时机从threadlocalmap中删除entry。
来看看ThreadLocal是怎么处理的,判断是否是statle Entry的代码很简单,就是entry.get()是否为空:
private int expungeStaleEntry(int staleSlot) { Entry[] tab = table; int len = tab.length; // expunge entry at staleSlot tab[staleSlot].value = null; tab[staleSlot] = null; size--; // Rehash until we encounter null Entry e; int i; for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) { ThreadLocal k = e.get(); if (k == null) { e.value = null; tab[i] = null; size--; } else { int h = k.threadLocalHashCode & (len - 1); if (h != i) { tab[i] = null; // Unlike Knuth 6.4 Algorithm R, we must scan until // null because multiple entries could have been stale. while (tab[h] != null) h = nextIndex(h, len); tab[h] = e; } } } return i; }可以看到会把从staleSlot到null entry这一段内所有的stale entry都删除掉,并且非stale的entry会重新rehash。保证stale slot所在的run(指两个null entry之间的所有entry)内不再有stale slot。但不是删除map内所有的stale entry。
另外一个删除stale entry的方法是:
private boolean cleanSomeSlots(int i, int n) { boolean removed = false; Entry[] tab = table; int len = tab.length; do { i = nextIndex(i, len); Entry e = tab[i]; if (e != null && e.get() == null) { n = len; removed = true; i = expungeStaleEntry(i); } } while ( (n >>>= 1) != 0); return removed; }可以看到内部调用了expungeStaleEntry,但是也有漏掉statle entry的情况,比如说在从i开始的log2(n)都不存在stale entry,但是其他地方存在stale的场景。
在get或者set中会调用上面的两个方法来删除部分stale,但是有可能不是全部。
所以存在内存泄露,记的把TheadLocal设置为static,然后调用remove方法。
0 0
- ThreadLocal源码分析
- Threadlocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析解密
- ThreadLocal源码分析
- java-----ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal的源码分析
- android-----ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal源码分析
- ThreadLocal的源码分析
- ThreadLocal源码简单分析
- 开启NOTE新时代 七款Android记事本软件推荐
- Image uImage与zImage的区别【转】
- UVA 331
- [模板]给dgrid表格添加自定义标签(自用)
- tomcat目录映射
- ThreadLocal源码分析
- Google Spanner原理:地球上最大的单一数据库
- Netty使用ExecutionHandler优化
- strncat, snprintf和strncpy对目标串结束符的不同处理方式
- Activity中finish() onDestroy() 和System.exit()的区别
- Spring MVC中的IoC容器初始化
- openwrt编译基本教程
- C语言中的EOF和feof()
- 自适应字体高度