Java并发编程之ThreadLocal源码分析(4)

entry节点不为null,entry节点的key和参数key不同
从i节点开始往后找,如果有key值相同的节点,也就是我们找到了我们需要的节点,返回entry即可。如果找不到,从i节点往后找,遇到key为null的回收一下该节点后返回null,遇到entry为null的直接返回null;

  getEntry()方法会被ThreadLocal的get()方法调用,我们会在稍后的ThreadLocal源码的讲解中再谈。
  介绍ThreadLocalMap用了不少的篇幅啊!下面就来看看我们ThreadLocal啦!关于ThreadLocal的方法网上已经有太多太多的文章介绍了。不过这里我们还是简单的结合我们上面所说的ThreadLocalMap来总结一下!

4 ThreadLocal源码分析 4.1 ThreadLocal.Set()方法 public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }

  当我们调用ThreadLocal对象的set方法时,程序会获取当前线程,并将其作为作为参数传递给getMap()方法。

Thread.java ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocal.java ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocalMap getMap(Thread t) { return t.threadLocals; }

  查看Thread类源码可以发现,Thread类中包含了一个ThreadLocalMap对象,这个家伙我们上面已经花了很大的篇幅来说了,简单的说它的key为ThreadLocal的弱引用,而value为待保存的对象。至于为什么是弱引用,大家自己去google下。
  继续说getMap()方法。getMap()方法很简单:返回当前线程中的ThreadLocalMap对象。

获取到ThreadLocalMap对象后,如果它不为空。则往该对象里面塞入一个键值对,key为ThreadLocal对象的弱引用,vaule为需要保存的对象。

如果ThreadLocalMap对象为null,则调用createMap()方法。

void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }

  createMap()方法在这里不细说。它会初始化当前线程的ThreadLocalMap对象,并将当前需要保存的对象放入ThreadLocalMap中,key值为当前线程的弱引用对象。
  小结一下:ThreadLocal的set方法会获取当前线程的ThreadLocalMap对象,如果TreadLocalMap对象不为空,则将当前线程的弱引用作用key,待保存对象作为value保存起来;若ThreadLocalMap对象为null,则会先初始化,再放入键值对。

4.2 ThreadLocal.Get()方法 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对象。那是自然,因为我们上面不就是往ThreadLocalMap里面放的吗!还记得ThreadLocalMap里面存了啥不?不记得的往上翻一翻。
  如果ThreadLocalMap对象不为空,当前线程作为key值,从ThreadLocalMap中取出来了一个ThreadLocalMap.Entry对象。这个getEntry()方法我们在上面已经已经介绍过了,可能再返回去看看。当然了,肯定有人要问!我们刚才放的时候放的明明不是ThreadLocalMap.Entry对象!这咋回事呢?

ThreadLocalMap.java static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } }

  实际上,在ThreadLocalMap中有一个静态类,它名叫Entry,继承了WeakReference类。再看看Entry的构造方法。如果调用Entry的get方法,实际上拿到的是ThreadLocal对象的弱引用对象。是不是很熟悉?上面的set方法有聊到过。
  继续说上面的get()方法。当我们拿到了Entry对象后,如果Entry对象不为空,直接返回Entry对象的value值,即我们想要的值。
那么如果ThreadLocalMap为空呢?则会执行setInitialValue()方法。光看名字,你肯定觉得它无非执行了两步操作:1.初始化对象;2. 将初始化后的对象塞入ThreadLocalMap对象中;3. 返回初始化后的对象。那我们来看看我们的猜想对不对呢?

private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d288123c4a13fedc48b5d93f52b5e9ed.html