0

0

详解Java中的ReferenceQueue与集合清理_软引用在缓存容器中的配合

P粉602998670

P粉602998670

发布时间:2026-02-26 10:57:10

|

186人浏览过

|

来源于php中文网

原创

referencequeue 通过 jvm gc 时将失效 reference 入队触发,需显式构造并手动 poll/remove 清理;软引用缓存须配合 concurrenthashmap 等结构防击穿,且清理逻辑应置于 put() 入口以避免内存泄漏。

详解java中的referencequeue与集合清理_软引用在缓存容器中的配合

ReferenceQueue 是怎么被触发的

它不会自动轮询,也不会主动通知你对象被回收了——只有当 JVM 在 GC 过程中发现某个 Reference(比如 SoftReference)所引用的对象可被回收时,才会把该 Reference 实例本身入队到关联的 ReferenceQueue 中。换句话说,ReferenceQueue 存的是“已被断开连接的引用对象”,不是原对象。

常见错误现象:queue.poll() 一直返回 null,以为没生效,其实是还没发生 GC,或者对象还够“软”(没到内存压力阈值);又或者忘了在构造 SoftReference 时传入 ReferenceQueue 实例。

  • 必须显式构造:比如 new SoftReference<string>(str, queue)</string>,不传 queue 就永远收不到通知
  • GC 后需手动调用 queue.poll()queue.remove() 拿出失效引用,否则队列会越积越多
  • remove() 会阻塞,poll() 立即返回,生产环境优先用 poll() 避免线程卡住

软引用缓存为什么不能只靠 get() 判断存活

SoftReference.get() 返回 null 只说明“此刻不可达”,但无法区分是刚被 GC 回收,还是压根没放进缓存、或 key 写错了。更麻烦的是:多个线程可能同时看到 null,然后各自重建对象,造成重复加载和资源浪费。

使用场景:做内存敏感型缓存(如图片解码结果、模板渲染上下文),既要尽量留着,又不能 OOM。

立即学习Java免费学习笔记(深入)”;

Descript
Descript

一个多功能的音频和视频编辑引擎

下载
  • 不能把 get() 结果直接当缓存命中处理,得配合外部结构(比如 ConcurrentHashMap)记录 key → reference 映射
  • 每次取值前先 get(),为 null 时再加锁重建,并把新 SoftReference 放回 map —— 否则并发下缓存击穿风险极高
  • 软引用对象即使没被回收,也可能因 JVM 内存策略提前清空(如 HotSpot 的 -XX:SoftRefLRUPolicyMSPerMB 参数影响),不能当成强一致性保障

ReferenceQueue 和 WeakHashMap 的行为差异

WeakHashMap 内部确实用了 ReferenceQueue,但它只用于清理 key,且清理时机不可控:只有当下一次调用 size()get()put() 等方法时,才顺带扫描并移除已入队的 key 条目。这不是实时的,也不是专用线程做的。

而你自己配 ReferenceQueue + SoftReference,控制权完全在手:可以定时扫、可以 GC 后立即扫、也可以在缓存 put 前主动 poll 一遍清理陈旧项。

  • WeakHashMap 不适合 value 大、需要主动释放资源的场景(比如缓存了 ByteBuffer 或文件句柄)
  • 它的 key 被回收后,entry 仍留在内部数组里,直到下次哈希操作触发清理 —— 可能长期占用内存
  • 如果你要清理的是 value(比如缓存值本身占内存多),必须自己管理 ReferenceQueueWeakHashMap 帮不上忙

清理逻辑放在哪里最容易漏掉

最常被忽略的位置是:缓存容器的 put() 入口。很多人只在 get() 里检查是否失效,却没在写入新值前清理队列里的旧引用,导致 ReferenceQueue 积压、map 中残留大量 null value 的映射、甚至 OutOfMemoryError: GC overhead limit exceeded

性能影响:频繁 poll() 几乎无开销;但若一次积压几千个,批量清理可能引起 minor GC 波动。

  • 建议在每次 put() 开始时,循环 queue.poll() 直到返回 null,逐个从缓存 map 中 remove 对应 key
  • 不要用 queue.remove() 配 while 循环,它可能无限阻塞(尤其测试时没触发 GC)
  • 如果缓存读远大于写,也可以另起一个低频调度任务(比如每 5 秒)清理,但必须确保清理逻辑是幂等的

ReferenceQueue 不是开关,它是个被动管道;软引用也不是缓存开关,它只是给 JVM 递了个“可商量”的请求。真正稳住缓存水位的,是你对入队、出队、映射维护这三步节奏的控制精度。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

850

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

248

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

906

2024.03.01

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

104

2023.09.25

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

721

2023.08.10

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

36

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.11.17

Golang 实际项目案例:从需求到上线
Golang 实际项目案例:从需求到上线

《Golang 实际项目案例:从需求到上线》以真实业务场景为主线,完整覆盖需求分析、架构设计、模块拆分、编码实现、性能优化与部署上线全过程,强调工程规范与实践决策,帮助开发者打通从技术实现到系统交付的关键路径,提升独立完成 Go 项目的综合能力。

1

2026.02.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.9万人学习

C# 教程
C# 教程

共94课时 | 10.2万人学习

Java 教程
Java 教程

共578课时 | 72.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号