25
2020
04

ThreadLocal 是什么?

ThreadLocal 是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,适用于各个线程不共享变量值的操作。
25
2020
04

ThreadLocal 工作原理是什么?

ThreadLocal 原理:每个线程的内部都维护了一个 ThreadLocalMap,它是一个 Map(key,value)数据格式,key 是一个弱引用,也就是 ThreadLocal 本身,而 value 存的是线程变量的值。也就是说 ThreadLocal 本身并不存储线程的变量值,它只是一个工具,用来维护线程内部的 Map,帮助存和取变量。数据结构,如下图所示:
25
2020
04

ThreadLocal 如何解决 Hash 冲突?

与 HashMap 不同,ThreadLocalMap 结构非常简单,没有 next 引用,也就是说 ThreadLocalMap 中解决 Hash 冲突的方式并非链表的方式,而是采用线性探测的方式。所谓线性探测,就是根据初始 key 的 hashcode 值确定元素在 table 数组中的位置,如果发现这个位置上已经被其他的 key 值占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置。源代码实现如下:/ * Increment i modulo len.
25
2020
04

ThreadLocal 的内存泄露是怎么回事?

ThreadLocal 在 ThreadLocalMap 中是以一个弱引用身份被 Entry 中的 Key 引用的,因此如果 ThreadLocal 没有外部强引用来引用它,那么 ThreadLocal 会在下次 JVM 垃圾收集时被回收。这个时候 Entry 中的 key 已经被回收,但是 value 又是一强引用不会被垃圾收集器回收,这样 ThreadLocal 的线程如果一直持续运行,value 就一直得不到回收,这样就会发生内存泄露。
25
2020
04

ThreadLocal 的应用场景有哪些?

ThreadLocal 适用于独立变量副本的情况,比如 Hibernate 的 session 获取场景。示例代码:private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();public static Session getCurrentSession(){    Session session =  threadLocal.get()
19
2020
02

解决 ThreadLocal 内存溢出的关键代码是什么?

答:关键代码为 threadLocal.remove() ,使用完 ThreadLocal 之后,调用remove() 方法,清除掉 ThreadLocalMap 中的无用数据就可以避免内存溢出了。
19
2020
02

ThreadLocal 为什么会发生内存溢出?

答:ThreadLocal 造成内存溢出的原因:如果 ThreadLocal 没有被直接引用(外部强引用),在 GC(垃圾回收)时,由于 ThreadLocalMap 中的 key 是弱引用,所以一定就会被回收,这样一来 ThreadLocalMap 中就会出现 key 为 null 的 Entry,并且没有办法访问这些数据,如果当前线程再迟迟不结束的话,这些 key 为 null 的 Entry 的 value 就会一直存在一条强引用链:Thread Ref -> Thread ->
19
2020
02

ThreadLocal 如何共享数据?

答:通过 ThreadLocal 的子类 InheritableThreadLocal 可以天然的支持多线程间的信息共享。
19
2020
02

为什么ThreadLocal变量要设置成 static 修饰?

如果把ThreadLocal声明为某个类的非静态变量,也就是实例变量,那么每次创建该类的实例时,都会导致创建等同的对象,这些重复的对象会导致浪费。
19
2020
02

ThreadLocal的应用场景

ThreadLocal适用于独立变量副本的情况,如果变量为全局共享的,则不适用了。一个典型的应用场景是数据库连接管理,每个线程访问数据库都应当是一个独立的Session会话,如果多个线程共享同一个Session会话,有可能出现其他线程关闭连接了,而当前线程再执行提交时出现会话已关闭的异常。如果采取ThreadLocal的方式能避免线程争抢Session,提高并发下的安全性。
19
2020
02

为什么 ThreadLocalMap 的 key 是弱引用?

如果 key 是强引用,那么发生 GC 时 ThreadLocalMap 还持有 ThreadLocal 的强引用,会导致 ThreadLocal 不会被回收,从而导致内存泄漏。弱引用 ThreadLocal 不会内存泄漏,对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,这算是最优的解决方案。