ThreadLocal源码图解

ThreadLocal源码图解.jpg

为何ThreadLocalMap.Entry的key需要被包装成WeakReference

复习引用类型

  1. 强引用(不解释)
  2. 软引用 SoftReference 如果内存不足,发生GC时可回收
  3. 弱引用 WeakReference 如果发生GC,会被立即回收
  4. 虚引用 PhantomReference(自行了解)

看下面代码

  1. ThreadLocal<String> tl = new ThreadLocal<>();

如上代码,new一个ThreadLocal对象,一旦tl被置为null,但是线程内部的ThreadLocalMap.Entry的key依然指向该对象,不就无法做回收动作,所以JDK设计者主动将其包装成WeakReference对象,这样就能保证一旦ThreadLocal对象失去了强引用,即使线程内有引用指向它,依然能够被回收掉

内存泄露产生的原因

如果tl被置为null,但是我们没有在代码做如下动作,就会存在内存泄露的风险

  1. ThreadLocal<String> tl = new ThreadLocal<>();
  2. try {
  3. tl.set("bingo");
  4. //TODO 业务逻辑
  5. } finally {
  6. tl.remove();//防止内存泄露
  7. }

如果tl被置为null,我们又不做tl.remove(),Entry中key指向的ThreadLocal对象被GC回收了,就指向null,但是Entry中value依然被驻留在内存中,这样就造成了内存泄露。