设为首页 加入收藏

TOP

Java并发编程之ThreadLocal内存泄漏探究(二)
2018-07-31 09:13:08 】 浏览:222
Tags:Java 并发 编程 ThreadLocal 内存 泄漏 探究
下所示:


Reference(T referent, ReferenceQueue<? super T> queue) {
  this.referent = referent;
  this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}


可知 k 被传递到了 WeakReference 的构造函数里面,也就是说 ThreadLocalMap 里面的 key 为 ThreadLocal 对象的弱引用,具体是 referent 变量引用了 ThreadLocal 对象,value 为具体调用 ThreadLocal 的 set 方法传递的值。


当一个线程调用 ThreadLocal 的 set 方法设置变量时候,当前线程的 ThreadLocalMap 里面就会存放一个记录,这个记录的 key 为 ThreadLocal 的引用,value 则为设置的值。


但是考虑如果这个 ThreadLocal 变量没有了其他强依赖,而当前线程还存在的情况下,由于线程的 ThreadLocalMap 里面的 key 是弱依赖,则当前线程的 ThreadLocalMap 里面的 ThreadLocal 变量的弱引用会被在 gc 的时候回收,但是对应 value 还是会造成内存泄露,这时候 ThreadLocalMap 里面就会存在 key 为 null 但是 value 不为 null 的 entry 项。


其实在 ThreadLocal 的 set 和 get 和 remove 方法里面有一些时机是会对这些 key 为 null 的 entry 进行清理的,但是这些清理不是必须发生的,下面简单讲解ThreadLocalMap 的 remove 方法的清理过程,remove 的源码,如下所示:


 


private void remove(ThreadLocal<?> key) {


  //(1)计算当前ThreadLocal变量所在table数组位置,尝试使用快速定位方法
  Entry[] tab = table;
  int len = tab.length;
  int i = key.threadLocalHashCode & (len-1);
  //(2)这里使用循环是防止快速定位失效后,变量table数组
  for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {
      //(3)找到
      if (e.get() == key) {
          //(4)找到则调用WeakReference的clear方法清除对ThreadLocal的弱引用
          e.clear();
          //(5)清理key为null的元素
          expungeStaleEntry(i);
          return;
      }
  }
}
 private int expungeStaleEntry(int staleSlot) {
            Entry[] tab = table;
            int len = tab.length;
            //(6)去掉去value的引用
            tab[staleSlot].value = null;
            tab[staleSlot] = null;
            size--;


            Entry e;
            int i;
            for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
                ThreadLocal<?> k = e.get();
                //(7)如果key为null,则去掉对value的引用。
                if (k == null) {
                    e.value = null;
                    tab[i] = null;
                    size--;
                } else {
                    int h = k.threadLocalHashCode & (len - 1);
                    if (h != i) {
                        tab[i] = null;
                        while (tab[h] != null)
                            h = nextIndex(h, len);
                        tab[h] = e;
                    }
              &n

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java迭代器升级版探究 下一篇C#语法——泛型的多种应用

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目