ThreadLocal

1.ThreadLocal是什么

ThreadLocal本地线程变量,线程自带的变量副本(实现了每一个线程副本都有一个专属的本地变量,主要解决的就是让每一个线程绑定自己的值,自己用自己的,不跟别人争抢。通过使用get()和set()方法,获取默认值或将其值更改为当前线程所存的副本的值从而避免了线程安全的问题)

 

 

 需要注意的是,使用ThreadLocal变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的ThreadLocal变量,可能会影像后序业务逻辑和造成内存泄露等问题。尽量在代理中使用try-finally块进行回收(阿里巴巴手册)

 

2.ThreadLocal、Thread、ThreadLocalMap关系

  • 根据官方API,Thread是程序中执行的线程;ThreadLocal类提供线程局部变量。

  • 先打开Thread.java类,发现每个Thread类里面有一个ThreadLocal

    •  

       

  • ThreadLocalMapThreadLocal的一个静态内部类

 

 

三者总概括脑图

 

 

 threadLocalMap实际上就是一个以threadLocal实例为key,任意对象为value的Entry对象
当我们为threadLocal变量赋值,实际上就是以当前threadLocal实例为key,值为value的Entry往这个threadLocalMap中存放

三、内存泄漏

什么是内存泄漏?

  • 不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露

ThreadLocal为什么会引发内存泄漏?

  • 当我们为ThreadLocal赋值,实质上是将ThreadLocal内部的Entry(KV键值对)的Value赋值,它的Key是ThreadLocal本身。当ThreadLocal强引用被设置为null,那么GC将会回收,那么Entry中的Key就会成为null,而Value不为空,如果不及时清除,就会发生内存泄漏

为什么要用弱引用

  • 因为强引用无法回收,所以用了弱引用,如果 ThreadLocal 对象没有被其他强引用持有,就可以被垃圾回收,从而避免了内存泄漏的问题。

怎么解决?

  • 即使调用remove()方法,从源码分析,set、getEntry、remove方法,在针对内存泄露方面,会通过expungeStaleEntry方法来清理掉key为null的enry

 

posted @ 2023-03-16 21:52  冬日寻雾记  阅读(58)  评论(0)    收藏  举报