zoukankan      html  css  js  c++  java
  • JDK ThreadLocal

    2019-03-29 周五 10:45 下午

    1. ThreadLocal 回顾:
      主要看 ThreadLocal#get()方法:
      public T get() {
          Thread t = Thread.currentThread();
          // 拿到当前线程中保存的 map
          ThreadLocalMap map = getMap(t); 
          if (map != null) {
              // 以 this (也就是用户创建的 ThreadLocal 对象)为 key
              // 获取到一个 Entry 对象,然后返回 value
              ThreadLocalMap.Entry e = map.getEntry(this);
              if (e != null) {
                  @SuppressWarnings("unchecked")
                  T result = (T)e.value;
                  return result;
              }
          }
          // 当 map 为 null 时,调用初始化方法,包括 ThreadLocalMap 的创建
          // 以及初始化 value
          return setInitialValue();
      }
      

    ThreadLocal 示意图

    1. 内存泄漏相关
      ThreadLocalMap 中的键值对是用 Entry 存储的,Entry 继承了 WeakReference 代码如下:

          static class Entry extends WeakReference<ThreadLocal<?>> {
              /** The value associated with this ThreadLocal. */
              Object value;
      
              Entry(ThreadLocal<?> k, Object v) {
                  super(k); // 调用父类构造方法,弱引用
                  value = v;// 强引用
              }
          }
      

      从构造方法中可以看到 entry 对 k 的引用是一个弱引用,对 v 的引用则是强引用。
      对 k 使用弱引用的原因是:当 map 外部没有对 ThreadLocal 对象的强引用时,说明这个 ThreadLocal 对象不需要了,k 在下一次 GC 时就会被回收。 如果不采用弱引用,因为某些线程的 map 对 ThreadLocal 对象还有强引用,导致其无法被回收掉。

      虽然对 k 使用了弱引用解决了前面提到的内存泄漏的问题,但是有引发了另一个内存泄漏的问题:
      如果线程一直在运行,那么该线程持有的 map 就不会被销毁,当外部没有对 ThreadLocal 对象的强引用时,经过一轮 GC,对应的 Entry 就变成了 null -> value 的情况,对 value 的引用是强引用,这就导致 Entry 对象始终无法释放掉。
      针对这个问题:在 ThreadLocalMap 的 set() 和 rehash()等方法中,会将 key 为 null 的 Entry 的 value 置为 null,使得 Entry 对象可以被回收。

      理论上来讲,ThreadLocal 还是可能会出现内存泄漏的,因为最后将 Entry 的 value 置为 null 的操作,不够及时(待确认)。
      建议:

      1. 一直持有 ThreadLocal 对象的强引用
      2. 如果当前线程不需要本地变量时,显示的调用 Threadloca 对象的 remove()方法

    参考

  • 相关阅读:
    jquery---stop()
    标准设备的-media queries
    CSS3 Media Queries
    css---------selector
    sublime----(1)
    XAMPP、WAMP、appserv
    Express.js----路由
    nodejs----上传显示图片
    node.js-----处理POST请求
    DotNetOpenAuth使用笔记
  • 原文地址:https://www.cnblogs.com/magexi/p/11619901.html
Copyright © 2011-2022 走看看