对ThreadLocal的一些理解

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。
如果想实现每一个线程都有自己的专属本地变量该如何解决呢?

JDK 中自带的ThreadLocal类正是为了解决这样的问题。
ThreadLocal类主要解决的就是让每个线程绑定自己的值


ThreadLocal与ThreadLocalMap的关系

java 复制代码
public class Thread implements Runnable {
    //......
    //与此线程有关的ThreadLocal值。由ThreadLocal类维护
    ThreadLocal.ThreadLocalMap threadLocals = null;

    //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    //......
}

ThreadLocalMap是ThreadLocal类的静态内部类,即一个对象,且ThreadLocalMap中存放的是Entry<K ,V>数组,每一个entry中存放的key为当前ThreadLocal对象,value为我set的值。

因为是静态内部类,所以多个ThreadLocal对象共用一个ThreadLocalMap。

一个Thread线程对象中只有一个ThreadLocalMap

【通过当前线程ID唯一对应一个ThreadLocalMap对象】

但是一个线程可以有多个ThreadLocal对象,当然只是可以....


ThreadLocal如何避免内存泄漏

什么是内存泄漏?

内存溢出:程序中的内存不够使用者继续分配。

内存泄漏:程序中动态分配的内存无法被释放(GC清理),长时间最终导致内存溢出。

这里涉及到弱引用,即entry对象中key对threadlocal对象的引用。

如果 ThreadLocal对象 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉(弱引用),而 value 不会被清理掉。【key是弱引用和value本身是强引用没有关系】

这样一来,ThreadLocalMap 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露

ThreadLocalMap 实现中已经考虑了这种情况,在调用 set()get()remove() 方法的时候,会清理掉 key 为 null 的记录。

remove核心为expungeStaleEntry(),清除完当前key为null的entry对象,然后还会遍历其他Entry,清空所有key为null的value和 entry作为一个兜底。

使用完 ThreadLocal方法后最好手动调用remove()方法

相关推荐
HanhahnaH13 分钟前
Spring集合注入Bean
java·spring
未定义.22119 分钟前
电子削铅笔刀顺序图详解:从UML设计到PlantUML实现
java·软件工程·uml
雾月5537 分钟前
LeetCode 1292 元素和小于等于阈值的正方形的最大边长
java·数据结构·算法·leetcode·职场和发展
24k小善2 小时前
Flink TaskManager详解
java·大数据·flink·云计算
想不明白的过度思考者2 小时前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV2 小时前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
晨集2 小时前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城2 小时前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
椰羊~王小美2 小时前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言