ThreadLocal 初探
符号说明
- tl: 一个ThreadLocal<U>对象
- u: 一个U类的对象
- m: Thread对象的threadLocalMap对象(ThreadLocalMap类是ThreadLocal类的静态内部类)
阅读源码后,总结下tl.set(u)
运行时发生了什么。
- 获取当前线程的m[注1]
- 计算index = tl的哈希值 & m的tab的length-1,获取tab在index处的Entry对象e
- 若e为null,则参照注1中,将index处指向new出来(以tl和u为参数)的Entry对象。方法结束。
- 否则获取e弱引用指向的ThreadLocal对象key
- 若key==tl,将e的value指向u,方法结束。
- 若key为null(场景:之前另一个ThreadLocal对象在当前线程运行时也调用了本文讨论的set方法,后来(在此之前)被gc了。这也引导我们理解为什么Entry要弱引用ThreadLocal对象:即使某个线程中有引用指向ThreadLocal对象,后者也能被回收),调用staleEntry方法……,方法结束。
- 步骤4的两个分支都不满足,循环给index加1重复步骤3、4,这边还没看懂…..
注
- 线程对象生成时m为null。如果此时m为null,则以tl和u为参数,生成m。m拥有一个Entry[] tab,tab的初始长度为16;Entry继承了WeakReference<ThreadLocal<?>>,拥有一个Object value,Entry的构造函数将this弱引用到tl,将value指向u;生成m时,以tl和u为参数,new了一个Entry对象e,令(tl的哈希值 & 15)的结果为index,将tab[index]指向e。方法结束。