本文最后更新于459 天前,其中的信息可能已经过时,如有错误请发送邮件到3368129372@qq.com
组成
ThreadLocal->ThreadLocalMap
->Entry1(key(ThreadLocal类型), value),Entry1(key(ThreadLocal类型), value)... ...
ThreadLocalMap类似于哈希map,线性探测法解决冲突,实现为
static class ThreadLocalMap {
  private static final int INITIAL_CAPACITY = 16;
  private Entry[] table;
  private int size = 0;
  private int threshold;
  private void setThreshold(int len) {
      this.threshold = len * 2 / 3;
  }
  private static int nextIndex(int i, int len) {
      return i + 1 < len ? i + 1 : 0;
  }
  private static int prevIndex(int i, int len) {
      return i - 1 >= 0 ? i - 1 : len - 1;
  }
  ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
      this.table = new Entry[16];
      int i = firstKey.threadLocalHashCode & 15;
      this.table[i] = new Entry(firstKey, firstValue);
      this.size = 1;
      this.setThreshold(16);
  }
  private ThreadLocalMap(ThreadLocalMap parentMap) {
      Entry[] parentTable = parentMap.table;
      int len = parentTable.length;
      this.setThreshold(len);
      this.table = new Entry[len];
      Entry[] var4 = parentTable;
      int var5 = parentTable.length;
      for(int var6 = 0; var6 < var5; ++var6) {
          Entry e = var4[var6];
          if (e != null) {
              ThreadLocal<Object> key = (ThreadLocal)e.get();
              if (key != null) {
                  Object value = key.childValue(e.value);
                  Entry c = new Entry(key, value);
                  int h;
                  for(h = key.threadLocalHashCode & len - 1; this.table[h] != null; h = nextIndex(h, len)) {
                  }
                  this.table[h] = c;
                  ++this.size;
              }
          }
      }
  }内存泄漏问题
- 
ThreadLocal的实现为 static class Entry extends WeakReference<ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super(k); this.value = v; } }可见key(即ThreadLocal)对象为弱引用。因为Thread能到达ThreadLocal,而Thread可能被线程池复用而长时间不销毁。因此需要改为弱引用,只存在弱引用时只要GC就被回收。 
 注:一般ThreadLocal作为某个类的成员变量而被强引用,这个类销毁时说明强引用消失,马上被GC)
- 为什么value不设成弱引用呢?因为value不会被作为成员变量而强引用,直接回收会导致ThreadLocal还在但是对应的值已经消失了!!!
- 在调用get方法时会检测对应的ThreadLocal(key)是否还存在,无则回收value值。
- 内存泄漏的情况:未使用remove(),且set()后未get()回收value,且线程被复用,Thread对象一直存在时。