内容提要
• ThreadLocal能定义线程本地变量;
• 从ThreadLocalMap进一步了解ThreadLocal特性;
• 结合底层代码,深入了解ThreadLocal;
• ThreadLocal可能会导致内存泄漏,如何避免?
• 总结:面试时通过底层代码,全面展示ThreadLocal的方式;
通过ThreadLocal,定义线程本地变量
• 也能通过ThreadLocal存储线程本地变量 ;
• 线程里可以使用定义在主内存里的变量 ;
• 用多个线程去爬取不同的网站,每个线程用自身的 ThreadLocal来维护爬取不成功的列表;
内部数据结构:ThreadLocalMap
• ThreadLocalMap里每个元素是Entry
• 是通过内部的ThreadLocalMap对象来存储本地变量
• 每个Entry是键值对,键是当前ThreadLocal对象,值是本地变量
• Entry是继承WeakReference,是弱引用,之上没强引用时会回收
内部数据结构:ThreadLocalMap
• 一个线程类里有一个ThreadLocalMap
• 一个线程类里可以有多个ThreadLocal类变量
• 一个ThreadLocalMap里有多个Entry
• 每个Entry存储了一个ThreadLocal本地变量
set方法的源码
• localVal.set(localVal.get() + 1);,调用时,传入一个参数
• 放入ThreadLocalMap对象,并用当前ThreadLocal对象作为Key
• 如没有ThreadLocalMap对象,则用当前线程t来创建
创建ThreadLocalMap
• 初始化时,用当前线程作为键
• 通过源代码,能发现ThreadLocalMap里的每个元素是Entry,初始 长度是16,Entry extends WeakReference
get方法的源码
• 通过当前线程,得到所属的ThreadLocaMap,以及Entry
• 从Entry里,获得value部分,这就是本线程的本地变量
可能会导致的内存泄漏
• 在ThreadLocal里保存值时,会放入Entry对象
• 但如创建ThreadLocal的线程一直持续运行,那么其中的value就 可能无法回收,
• Entry是基于弱引用,如创建ThreadLocal的线程终止,会回收
• 避免方式,用好ThreadLocal对象,需要及时remove
总结:如何全面展示ThreadLocal
1. 除了被问到,还可以主动引出:在xx业务里,我们需要用到 ThreadLocal来保存本地变量
2. 讲完业务后同时指出,ThreadLocal的内部实现是ThreadLocalMap
3. 结合ThreadLocal和ThreadLocalMap的源代码,讲述赋值和取值的 细节
4. 结合Entry和弱引用,讲述可能引发内存泄漏,同时说下如何避免
5. 通过本小节给出说辞,大家不仅能展示“存储线程本地变量”的技能, 还能让面试官感觉你熟悉底层代码,更进一步,还能通过弱引用,引导到垃圾回收话题