本文转载自微信公众号“小姐姐的味道”,作者小姐姐养的狗。转载本文请联系味觉小姐公众号。阅读本文需要先对ThreadLocal有一个大概的了解。不要啰嗦,开门见山。标签:[多层次][Java][源码]1.问一系列四个问题:ThreadLocal的原理?内存泄漏的原因?你用过InheritableThreadLocal吗?Netty的FastThreadLocal是什么?2.分析ThreadLocal作为实现“线程关闭”最重要的编程手段,经常被使用。比如传统的SimpleDateFormat,就不是线程安全的。如果声明为全局变量,在并发环境下会出现时间混乱。一个好的解决方案是使用ThreadLocal。ThreadLocal的使用非常广泛。比如Spring的事务管理就是通过它来实现的。但它也有一些弱点。不能透传(不能被子线程获取),于是诞生了InheritableThreadLocal以及更高级的封装库。3.回答3.1ThreadLocal的原理?看完源码不难回答。如下图所示(这张图是最容易理解的),ThreadLocal的get和remove方法只是使用的快捷方式。它的真实数据存在于线程中一个叫做ThreadLocalMap的结构中。一个ThreadLocal值会根据不同的线程分散到N个线程中。所以要得到ThreadLocal的Value,有两个步骤。第一步是根据线程获取Map。第二部分是根据自身从Map中获取value,所以它的this就是Map的Key,没有意义。这是一种照顾编码习惯的数据结构。3.2内存泄漏的原因?严格来说,ThreadLocal没有内存泄漏。如果是这样,您忘记实现remove方法。这是由于使用不当造成的。这与其他一些内存泄漏问题是一致的,例如:流没有关闭,连接没有断开。为什么在滥用静态地图时会出现泄漏问题?如果不调用remove方法,ThreadLocal对应的值会一直存在,直到当前线程Destruction为止。众所周知,线程的生命周期是比较长的,现在常用的线程池会让线程的生命周期变长。没有remove,当然不会被release。这个和Key是不是弱引用关系不大。在这种情况下,是否是泄漏问题是措辞问题。面试的过程是讨论,不一定是标准答案。与内存泄漏问题相比,线程池导致的数据乱序问题更值得关注。因为放在ThreadLocal中的数据肯定不会很大,泄漏只会占用一点内存;而且数据杂乱无章,反而会造成业务bug。3.3你用过InheritableThreadLocal吗?InheritableThreadLocal在父子线程之间传值的时候已经使用了,解决了threadlocal无法在父子线程之间传值的问题。这本质上是通过Thread实现的。通过两个Map复制属性。/*ThreadLocalvaluespertainingtothisthread.Thismapismaintained*bytheThreadLocalclass.*/ThreadLocal.ThreadLocalMapthreadLocals=null;/**InheritableThreadLocalvaluespertainingtothisthread.Thismapis*maintainedbytheInheritableThreadLocalclass.*/ThreadLocal.ThreadLocalMapinheritableThreadLocals=null;线程被缓存以供重复使用。这时候父子线程关系的上下文传递是没有意义的。附加问题:你是如何解决的?阿里这边有个库,https://github.com/alibaba/transmittable-thread-local,专门解决变量跨线程共享的问题。面对阿里,还不如顺便舔一下。3.4什么是Netty的FastThreadLocal既然Java中有了ThreadLocal类,Netty为什么要创建一个结构体叫FastThreadLocal呢?我们先来看ThreadLocal的实现。在Thread类中,有一个成员变量threadLocals,里面存放了所有与这个线程相关的自定义信息。这个变量的定义是在Thread类中,但是操作是在ThreadLocal类中。问题在于ThreadLocalMap类。虽然叫Map,但是并没有实现Map接口。如图,ThreadLocalMap在rehash时,并没有使用类似HashMap的数组+链表+红黑树。它只使用一个数组,采用开放式寻址(遇到冲突时,依次查找直到空闲位置)的方式,这种方式效率很低。由于Netty使用ThreadLocal的频率很高,所以Netty专门对其进行了优化。之所以快,是因为它做了底层数据结构的文章,使用常量下标定位元素,而不是使用JDK默认的检测算法。底层的InternalThreadLocalMap也会相应地优化缓存行。作者简介:品味小姐姐(xjjdog),一个不允许程序员走弯路的公众号。专注于基础架构和Linux。十年架构,每天百亿流量,与你探讨高并发世界,给你不一样的滋味。我的个人微信xjjdog0,欢迎加好友进一步交流。
