ThreadLocal
线程封闭
对象封闭在一个线程里,即使这个对象不是线程安全的,也不会出现并发安全问题
栈封闭:就是用栈(stack)来保证线程安全
public void testThread() {
StringBuilder s = new StringBuilder();
s.append("Hello");
}
StringBuilder 是线程不安全的,但是它只是个局部变量,局部变量存储在虚拟机栈,虚拟机栈是线程隔离的,所
以不会有线程安全问题.
ThreadLocal 线程封闭:简单易用使用 ThreadLocal 来实现线程封闭,线程封闭的指导思想是封闭,而不是共享。
所以说 ThreadLocal 是用来解决变量共享的并发安全问题,多少有些不精确。
什么是ThreadLocal
ThreadLocal 叫做线程变量,意思是 ThreadLocal 中填充的变量属于当前线程,该变量对其他线程而言是隔离的。
ThreadLocal 原理分析
首先 ThreadLocal 是一个泛型类,保证可以接受任何类型的对象。因为一个线程内可以存在多个 ThreadLocal 对
象,所以其实是 ThreadLocal内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是ThreadLocal
实现的一个叫做 ThreadLocalMap 的静态内部类。而我们使用的get()、set() 方法其实都是调用ThreadLocalMap
类对应的 get()、set()方法
ThreadLocal 可以理解为只是 ThreadLocalMap 的封装,传递了变量值。数据最终存在了ThreadLocalMap中。
ThreadLocal 内存泄漏问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aPdikKE0-1626956800688)(I:\HJ2010\CSDN笔记\threadlocal 内存泄漏问题.jpg)]
TreadLocalMap 使用 ThreadLocal 的弱引用作为 key,如果一个 ThreadLocal 不存在外部强引用时,
Key(ThreadLocal)势必会被 GC 回收,这样就会导致ThreadLocalMap 中 key 为 null, 而 value 还存在着强引
用,只有 thead 线程 退出以后,value 的强引用链条才会断掉。但如果当前线程再迟迟不结束的话,这些 key 为
null 的 Entry 的 value 就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value
永远无法回收,造成内存泄漏。
key 使用强引用
当 ThreadLocalMap 的key 为 强 引用 回 收 ThreadLocal 时 , 因 为ThreadLocalMap 还 持 有hreadLocal的 强
引 用 , 如 果 没 有 手 动 删 除 ,ThreadLocal 不会被回收,导致 Entry 内存泄漏。
key 使用弱引用
当 ThreadLocalMap 的 key 为 弱 引 用 回 收 ThreadLocal 时 , 由 于ThreadLocalMap 持 有 ThreadLocal 的 弱
引 用 , 即 使 没 有 手 动 删 除 ,ThreadLocal 也会被回收。当 key 为 null,在下一次 ThreadLocalMap 调用
set(),get(),remove()方法的时候会被清除 value 值。
ThreadLocal 正确的使用方法
eadLocalMap 调用
set(),get(),remove()方法的时候会被清除 value 值。
ThreadLocal 正确的使用方法
每次使用完 ThreadLocal 都调用它的 remove()方法清除数据.