被面试官问懵了,ThreadLocal的key为什么设置成弱引用?

ThreadLocal源码夺命12问,你能坚持到第几问? 总结的面试题也挺费时间的,文章会不定时更新,有时候一天多更新几篇,如果帮助您复习巩固了知识点,还请三连支持一下,后续会亿点点的更新!,展开后有一张办公桌大小,也可以折叠成一本书的尺寸,有兴趣的小伙伴可以了解一下,当然,不管怎样博主的文章一直都是免费的~为了帮助更多小白从零进阶 Java 工程师,从优快云官方那边搞来了一套 《Java 工程师学习成长知识图谱》,尺寸。此外,在线性的向前、向后遍历数组寻找目标元素所在的桶位时,如果发现数据过期了(,桶的位置是(数组索引),不同位置上,不发生。 阅读详情
AI摘要

本文解析ThreadLocal面试中的常见问题,重点讲解为何key设置为弱引用以防止内存泄漏,而value不设为弱引用的原理。通过实例演示理解内存管理与脏数据的避免。

前言

想起来去年九月夜郎自大,面过一次蚂蚁金服,一面面试官上来一串ThreadLocal的连环炮直接把我干懵了……虽然现在回想起来问得都挺简单,不过还是来做一发总结,希望看到这篇文章的小伙伴以后就不要栽坑里了。

面试连环炮

先来体验一下关于ThreadLocal的连环炮:

  1. ThreadLocal是什么?项目中用到过吗?
  2. ThreadLocal的结构是怎么样的?
  3. 使用ThreadLocal需要注意哪些问题?
  4. 为什么key要设置成弱引用呢?
  5. 那为什么value不设置成弱引用呢?ThreadLocalMap不是持有对这个value的强引用,它还会被回收吗?
  6. 为什么会出现内存泄漏?你是怎么发现内存泄漏的?
  7. 怎么避免出现脏数据问题?

其实说实话,这几个问题都不难,稍微对ThreadLocal有点了解的都能答上来,关键在于第4个问题和第5个问题。

key为什么要设置成弱引用?

先来看看ThreadLocalMap对key和value的构造:

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;
    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

在set方法中,会将key和value以entry对象进行存储,key就是我们的Threadlocal引用,value就是我们要设置的值。

这里我们观察Entry这个类就会发现,它继承了WeakReference类,并且在构造方法中,将key设置成了弱引用,而value则是强引用。

为什么要这样做?

要知道,ThreadlocalMap是和线程绑定在一起的,如果这样线程没有被销毁,而我们又已经不会再某个threadlocal引用,那么key-value的键值对就会一直在map中存在,这对于程序来说,就出现了内存泄漏。

为了避免这种情况,只要将key设置为弱引用,那么当发生GC的时候,就会自动将弱引用给清理掉,也就是说:假如某个用户A执行方法时产生了一份threadlocalA,然后在很长一段时间都用不到threadlocalA时,作为弱引用,它会在下次垃圾回收时被清理掉。

而且ThreadLocalMap在内部的set,get和扩容时都会清理掉泄漏的Entry,内存泄漏完全没必要过于担心。

value为什么不设置成弱引用

回答完上面的问题,面试官紧接着就会问你:

“那照你的说法,value也应该设置成弱引用才对呀?不然不是一样会发生内存泄漏?”

对于这个问题,如果没有仔细思考,猝不及防下可能就会被问懵,对啊,既然key设置成弱引用的好处这么明显,那为什么value不也设置成弱引用呢?

我们来看下面一段代码:

public static void main(String[] args) throws Exception {
    Map<WeakReference<Integer>, WeakReference<Integer>> map = new HashMap<>(8);
    WeakReference<Integer> key = new WeakReference<>(666);
    WeakReference<Integer> value = new WeakReference<>(777);
    map.put(key,value);
    System.out.println("put success");
    Thread.sleep(1000);
    System.gc();
    System.out.println("get " + map.get(key).get());
}

猜一下结果会怎样?

完蛋了,我在方法里执行我的代码时居然会出现空指针??

可能有些小伙伴不太懂,明明有value这个强引用啊?

可惜value这个强引用是指向new WeakReference<>(777)的,也就是说,777这个才是我们真正存进去的对象,这时候它已经不存在任何强引用了,所以理所当然的会被清理掉啦。

所以为什么value为什么不设置成弱引用的原因不用我说大家也应该清楚了。

最后留个小彩蛋,上面这段代码,如果换成下面:

public static void main(String[] args) throws Exception {
    Map<WeakReference<Integer>, WeakReference<Integer>> map = new HashMap<>(8);
    // 注意这里~
    WeakReference<Integer> key = new WeakReference<>(1);
    WeakReference<Integer> value = new WeakReference<>(2);
    map.put(key,value);
    System.out.println("put success");
    Thread.sleep(1000);
    System.gc();
    System.out.println("get " + map.get(key).get());
}

猜一下结果会怎样?

ThreadLocal内存泄漏深度解析:从弱引用到线程池排查 在Java并发编程中,引用类型与JVM内存回收机制是理解对象生命周期的基石。弱引用与强引用的差异,决定了对象何时能被GC回收,也直接影响着线程局部变量的安全性。ThreadLocal作为线程隔离的常用工具,其底层ThreadLocalMap中Entry的key采用弱引用、value却为强引用,当外部强引用断开后,value仍可能被线程持有,形成内存泄漏隐患。理解这一原理,不仅能解释为何单纯依赖弱引用无法根除问题,更能指导我们在线程池复用、高并发请求等场景下正确使用remove清理,并借助jmap、MAT等工 阅读详情

相关推荐

首个FDA认证开源医学影像AI平台Comp2Comp:从CT自动分析到临床部署全解析

深度学习模型在医学影像分析领域正成为变革性力量,其核心原理是通过卷积神经网络自动学习图像特征,实现精准分割与检测。这一技术价值在于将高度依赖医生经验的定性、主观判断,转化为高效、客观、可重复的定量分析,极大提升了诊断的一致性和工作效率。在应用场景上,医学影像AI已广泛渗透于疾病筛查、辅助诊断、预后评估及治疗方案规划等多个环节。本文聚焦于获得FDA 510(k)认证的开源平台Comp2Comp,它集成了主动脉钙化评分和椎体骨密度分析双任务,通过串联式的U-Net分割网络与目标检测模型,构建了从DICOM预处理

weixin_33725126的博客 653

ThreadLocal总结

JDK在设计时也考虑到key被收到时导致内存泄漏问题,在调用ThreadLocal中set、remove、rehash时会扫描key为null的entry,并将value置为null,避免内存泄漏,但是这种需要调用threadLocal的这些方法时才能触发,如果此时threadlocal已经被回收了还是会存在内存泄漏问题,最好的还是我们再不使用时,手动调用remove处理。a、栈为强引用、entry的key为弱引用,栈方法执行结束后此时可以正常回收threadlocal对象。...

J 博客 1514

OpenIddict实战指南:在.NET Core中构建安全的OAuth 2.0与OpenID Connect服务

本文详细介绍了如何在.NET Core中使用OpenIddict框架构建安全、标准的OAuth 2.0与OpenID Connect授权服务。内容涵盖从快速搭建授权服务器、理解核心配置与授权流程,到集成用户数据库、实现完整登录授权,以及生产环境下的安全加固与部署指南,为.NET开发者提供了一套现代、可维护的认证授权解决方案。

weixin_29229989的博客 354

Threadlocal中的弱引用到底是怎么一回事

最近在复习面试资料的时候,偶然间看到了有人觉得Threadlocal的一个缺点是内存泄漏,顺着他的博客往下看,他就是觉得在entry中的key存在着对threadlocal实例对象的弱引用,然后就觉得在一次gc以后会因为key为null但是value还有值从而造成内存泄漏。 我左思右想,还是觉得不对劲,再查看相关文献和源码的时候才恍然大悟——人家早就是有预谋的使用弱引用好吗。。。可是说到这里有人会说这个人到底在讲什么??那么现在我们理顺思路重新讲呗 什么是Threadlo...

m0_59602613的博客 7046

Python+ArcGIS实战:5步搞定土壤类型预测(附随机森林模型配置技巧)

本文详细介绍了如何结合Python与ArcGIS,利用随机森林模型进行土壤类型预测。通过5个核心步骤——数据预处理、样本创建、模型构建、空间预测与精度验证,构建了一套自动化、高精度的空间预测工作流,并提供了关键的模型配置与调参技巧,助力GIS开发者高效完成土壤制图任务。

weixin_29227585的博客 396

R语言计算植物群落重要值:从基础概念到优势种判定

在植被生态学研究中,重要值是衡量物种在群落中地位的核心指标,它综合了相对多度、相对频度与相对显著度三个维度,能够客观反映物种的数量优势、分布广度与空间占据能力。理解重要值的生态学逻辑,是开展群落分类、优势种判定及多样性分析的基础。而R语言凭借其批量处理、可复现和与后续多元统计无缝衔接的优势,成为生态学研究者处理样方数据的高效工具。从野外记录的宽表到标准化长表,再到分组汇总计算相对指标,R语言能够显著提升数据处理效率与准确性。本文以实测群落数据为例,系统梳理重要值的两种算法口径、基于dplyr和tidyr的完

weixin_42634811的博客 265

【JVM】为什么ThreadLocal被设计为弱引用

为什么ThreadLocal被设计为弱引用

weixin_46956020的博客 2402

hcaptcha-challenger:基于本地AI模型自动破解验证码的工程实践

验证码作为区分人类与机器的经典安全机制,其核心原理是通过图像识别、行为分析等交互式挑战来阻挡自动化程序。传统绕过方法依赖第三方打码平台或脚本,存在成本高、稳定性差的问题。随着多模态大语言模型和计算机视觉技术的发展,本地化AI求解成为新的技术方向,它通过集成YOLO、ResNet等模型,在本地完成图像语义理解,实现了高隐私、低成本、可进化的验证码自动化解决方案。这种范式尤其适用于需要大规模稳定处理网页交互的场景,如电商数据采集和社交媒体管理。hcaptcha-challenger项目正是这一理念的工程实践,它

weixin_42587866的博客 1025

⛳面试题-简述并分析ThreadLocalMap的key为什么是弱引用

注意:因为 ThreadLocal 的使用规范是使用 static final 进行修饰,所以 ThreadLocal 是存放在常量池的,不容易被回收,所以,ThreadLocalMap 在使用 ThreadLocal 对象作为 key 的时候需要使用弱引用,以保证不会出现内存泄漏;然而,需要注意的是,由于弱引用的特性,在某些情况下可能会导致 key 被提前回收,导致数据访问异常,因此在使用 ThreadLocal 时也需要注意合理的生命周期管理,避免出现意外情况;ThreadLocal 源码结构。

松柏123的博客 1742

FFmpeg HDR视频转SDR视频命令

之前蓝光盘电影多是AVC 1080p 8bit SDR格式视频,近两年4K电影流行,下载的蓝光电影多是HEVC 2160p 10bit HDR视频格式。 ffprobe查看有如下属性: # 10bit HDR Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x2160 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98

彼此当年少,莫负好时光 1万+

SMETANA 安装使用教程

关于SMETANA的安装和简单使用信息

qq_44940977的博客 1169

【ThreadLocal 】史上最全ThreadLocal 详解(二)原理,内存泄露,为什么不将key设置为强引用, 那么为什么 key 要用弱引用

【ThreadLocal 】史上最全ThreadLocal 详解(二)原理,内存泄露,为什么不将key设置为强引用, 那么为什么 key 要用弱引用

qq120631157的博客 959

【100%通过率】华为OD机试真题 Python 实现【高矮个子排队】【2023 Q2 | 100分】

我们现在希望小朋友排队,以“高”“矮”“高”“矮”顺序排列,每一个“高”位置的小朋友要比相邻的位置高或者相等;要求小朋友们移动的距离和最小,第一个从“高”位开始排,输出最小移动距离即可。移动距离的定义如下所示:第二位小朋友移到第三位小朋友后面,移动距离为1,若移动到第四位小朋友后面,移动距离为2。现在有一队小朋友,他们高矮不同,,我们以正整数数组表示这一队小朋友的身高,如数组{5,3,1,2,3}。1:其实题目理解之后就知道,目标是要保证最小移动距离,且以高位为起点。2:try catch 异常处理。

MISAYAONE的博客 3144

都说ThreadLocal被面试官问烂了,可为什么面试官还是喜欢继续问

面试官:有如下场景:在多线程并发情况下,有一个共享变量,不同线程设置不同值后,各线程只想获取自己设置的值,如何实现?小小白:使用ThreadLocal,...

JavaQ 1万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

面试官:为什么 ThreadLocalMap 的 key ThreadLocal 是弱引用?

面试官:今天要不来聊聊ThreadLocal吧? 候选者:我个人对ThreadLocal理解就是 候选者:它提供了线程的局部变量,每个线程都可以通过set/get来对这个局部变量进行操作 候选者:不会和其他线程的局部变量进行冲突,实现了线程的数据隔离 面试官:你在工作中有用到过ThreadLocal吗? 候选者:这块是真不多,不过还是有一处的。就是我们项目有个的DateUtils工具类 候选者:这个工具类主要是对时间进行格式化 候选者:格式化/转化的实现是用的SimpleDateForma

分享Java技术知识,共同成长进步! 2718

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ThreadLocal的弱引用之谜:为什么Java要这样设计?

强引用(Strong Reference):普通的对象引用,只要存在就不会被GC回收2.软引用(Soft Reference):内存不足时会被GC回收3.弱引用(Weak Reference):只要GC就会回收4.虚引用(Phantom Reference):几乎等同于没有引用// 强引用// 弱引用防止ThreadLocal对象本身的内存泄漏当外部强引用消失时,允许GC回收key虽然value可能暂时泄漏,但比key和value都泄漏要好弱引用不是银弹。

全栈开发工程师 1145

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

弱引用什么时候被回收_面试官:ThreadLocal为什么会发生内存泄漏?

前言ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。但是如果滥用 ThreadLocal,就可能会导致内存泄漏。下面,我们将围绕三个方面来分析 ThreadLocal 内存泄漏的问题ThreadLocal 实现原理ThreadLocal为什么会内存泄漏ThreadLocal 最佳实践Thread...

weixin_39948210的博客 2915

java面经——为什么ThreadlocalMap的key要设计成弱引用?

设计选择解决的问题剩余风险开发者责任弱引用 key防止 ThreadLocal 对象内存泄漏value 可能泄漏(需被动/主动清理)建议及时调用remove()强引用 key无key 和 value 均可能泄漏必须严格手动管理。

m0_56775120的博客 1882

面试官:你说说ThreadLocal为什么会导致内存泄漏?

1. 前言 “ThreadLocal为什么会导致内存泄漏,如何避免?” 这是笔者在面试阿里时,面试官提出的问题,当时回答的并不好,今天刚好有时间,决定复盘一下,彻底弄清楚内存泄漏的原因,并分享给大家。 1.1 何为内存泄漏? 首先我们有必要了解,到底何为「内存泄漏」?笔者这里引用百度百科的解释。 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 站在Java的角度来说,就是JVM创建的对象永远

程序员小潘 3851

为什么 ThreadLocalMap 的 key 是弱引用 value是强引用

弱引用 key 降低了 ThreadLocal 对象本身的内存泄漏风险、强引用 value 保证了数据的可用性。但最终避免内存泄漏、需要开发者养成良好的习惯、及时清理 ThreadLocal。

wy990880的博客 1238

被问 ThreadLocal 内存泄露,我说了句“因为它是弱引用”,面试官竟然让我当场画内存图。

ThreadLocal 就像一把锋利的手术刀,用得好可以优雅地实现跨层参数传递(比如 RAG 系统里的上下文追踪),用得不好就是生产环境的定时炸弹。记结构:数据在 Thread 里,不在 ThreadLocal 里。懂引用:弱引用是给回收留后路,不是泄露的元凶。防泄露:线程池 +remove()是唯一正解。下次面试官再让你画图,你就大大方方地把Thread到Value的那条引用链画出来,顺便聊聊线程池的复用机制。

Tjy2186987211的博客 1048

反问面试官3个ThreadLocal的问题

接下来,我想先说说ThreadLocal的用法和使用场景,然后反问面试官3个关于ThreadLocal的话题。

程序员半支烟,wechat:yclxiao 970

Java ThreadLocal 内存泄漏本质:弱引用为什么无法完全避免静态变量泄漏

在 Java 后端面试与生产排障中,“ThreadLocal 内存泄漏”是一个老生常谈但八成应聘者都讲不透的经典问题。很多人在背诵八股文时,通常会说出这样的标准答案:“ThreadLocal 的 Entry 键是弱引用,GC 时会被回收,但值是强引用,如果不手动调用remove(),就会发生内存泄漏”。今天我们深入 OpenJDK 源码底层,彻底扒开 ThreadLocalMap 的内存引用链路,理清弱引用设计的真实妥协与工程防线。

cannonjinx的博客 4699

一个ThreadLocal和面试官大战30个回合

安琪拉的博客 喜欢蹲草的纯粹技术人,用心分享一些互联网的技术 45篇原创内容 ...

安琪拉的博客 2122

为什么ThreadLocal要求用static修饰?从弱引用到内存泄漏的底层原理

在Java并发编程中,线程上下文传递常用ThreadLocal实现,但很多人并不清楚为什么阿里规范要求ThreadLocal必须使用static修饰。理解这个问题,需要从ThreadLocal在JVM中的本质角色说起。ThreadLocal本身并不存储值,它只是线程内部ThreadLocalMap的key,真正存放数据的是每个线程各自持有的Map。如果ThreadLocal作为非static成员变量随宿主对象频繁创建,多个ThreadLocal实例会拥有不同的哈希码,导致线程Map中出现多个互不可见的key

weixin_32822843的博客 237
上一篇: 想不到吧,Java创建线程的方式只有一种
下一篇: 我惊了:你居然认为ReentrantLock是轻量级锁?
评论 15
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值