Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
解决Caffeine缓存意外返回Null:配置与生命周期最佳实践_创想鸟

解决Caffeine缓存意外返回Null:配置与生命周期最佳实践

解决Caffeine缓存意外返回Null:配置与生命周期最佳实践

本文探讨caffeine缓存中`getifpresent`意外返回null的问题,主要归因于`weakkeys()`、`weakvalues()`的误用导致条目被垃圾回收,以及缓存实例生命周期管理不当(非`static final`)导致的缓存重置。教程将详细解释这些机制,并提供正确的配置与管理策略,确保缓存按预期工作,从而避免数据意外丢失。

Caffeine是一个高性能的Java本地缓存库,广泛应用于需要快速访问和临时存储数据的场景。然而,在使用Caffeine时,开发者有时会遇到缓存中明明已存入数据,但通过getIfPresent()方法却意外获取到null的情况。这通常不是Caffeine本身的bug,而是由于对缓存的配置和生命周期管理存在误解。

核心问题分析:弱引用与垃圾回收

在Caffeine的配置中,weakKeys()和weakValues()是两个强大的选项,它们允许缓存的键或值被JVM的垃圾回收器(GC)回收,即使它们仍在缓存中。

weakKeys(): 当一个键被配置为弱引用时,如果除了缓存本身之外,没有其他强引用指向这个键对象,那么该键及其对应的缓存条目就可能在下一次垃圾回收时被清除。对于像Long这样的包装类型,虽然它们是对象,但由于其值的特殊性,通常会被JVM缓存或内部化,因此weakKeys()可能不是导致Long类型键被回收的主要原因,除非键对象本身是一个非内部化的、无其他强引用的自定义对象。

weakValues(): 这是导致缓存值意外消失的更常见原因。当一个值被配置为弱引用时,如果除了缓存本身之外,没有其他强引用指向这个值对象,那么该值及其对应的缓存条目就可能在下一次垃圾回收时被清除。这意味着,如果一个SmsData对象被创建,然后立即放入缓存,并且在应用程序的其他任何地方都没有强引用持有这个SmsData对象,那么它就可能在短时间内被GC回收,导致getIfPresent()返回null。

考虑以下原始的缓存配置:

private Cache codeCache = Caffeine.newBuilder()        .expireAfterWrite(24, TimeUnit.HOURS)        .weakKeys()        .weakValues()        .build();

当使用weakValues()时,如果SmsData对象在put到codeCache后,在方法作用域外没有被其他强引用持有,那么它就成为了垃圾回收的候选对象。JVM的GC可以在任何时候回收这些弱引用的值,从而导致缓存条目消失。

何时使用弱引用?弱引用并非一无是处。它们在某些特定场景下非常有用,例如:

缓存大型对象,但这些对象在应用程序的其他部分也有强引用,你希望当其他强引用消失时,缓存也能自动释放内存。实现元数据缓存,当元数据关联的主对象被回收时,元数据也应被回收。然而,对于大多数常规缓存场景,我们希望缓存能够强引用其值,直到过期策略生效或手动移除。因此,除非你明确理解并需要弱引用的行为,否则应避免使用weakKeys()和weakValues()。

核心问题分析:缓存实例的生命周期管理

另一个导致Caffeine缓存行为异常的常见原因是缓存实例的生命周期管理不当。如果缓存实例不是一个单例或长寿命对象,那么每次需要使用缓存时都可能创建新的缓存实例,导致之前存储的数据丢失。

考虑以下原始的缓存声明:

private Cache codeCache = Caffeine.newBuilder()        // ... 配置 ...        .build();

如果这个codeCache是一个普通类的实例字段,并且这个类本身是每次请求或每次操作时都会被重新创建的,那么每次创建这个类的实例时,都会创建一个全新的Cache对象。这意味着,在一个实例中put的数据,在另一个新实例中尝试get时,将无法找到,因为它们是不同的缓存实例。

存了个图 存了个图

视频图片解析/字幕/剪辑,视频高清保存/图片源图提取

存了个图 17 查看详情 存了个图

推荐策略:对于应用程序级别的缓存,通常期望它是一个全局的、单例的资源,其生命周期与应用程序的生命周期一致。实现这一目标的方法通常有两种:

使用static final字段:将缓存声明为static final,确保它只在类加载时初始化一次,并且在整个应用程序生命周期中都只有一个实例。依赖注入(DI)框架管理:如果项目使用了Spring等依赖注入框架,可以将Caffeine Cache实例声明为一个@Bean,并设置为单例作用域。框架会负责管理其生命周期,确保每次注入的都是同一个缓存实例。

解决方案与最佳实践

基于上述分析,解决Caffeine缓存意外返回null问题的核心在于:移除不必要的弱引用配置,并确保缓存实例的生命周期管理得当。

1. 修正后的Caffeine缓存配置

首先,移除weakKeys()和weakValues()。除非有非常明确的理由和场景需要它们,否则应避免使用,以确保缓存中的值被强引用持有。

import com.github.benmanes.caffeine.cache.Cache;import com.github.benmanes.caffeine.cache.Caffeine;import java.util.concurrent.TimeUnit;// 假设 SmsData 是一个自定义的数据类class SmsData {    private int sendCount;    private int checkCount;    public int getSendCount() { return sendCount; }    public void setSendCount(int sendCount) { this.sendCount = sendCount; }    public int getCheckCount() { return checkCount; }    public void setCheckCount(int checkCount) { this.checkCount = checkCount; }    @Override    public String toString() {        return "SmsData{" +               "sendCount=" + sendCount +               ", checkCount=" + checkCount +               '}';    }}public class CaffeineCacheService {    // 推荐的Caffeine缓存配置:    // 1. 声明为 static final,确保缓存实例是单例且生命周期与应用程序一致。    // 2. 移除 weakKeys() 和 weakValues(),确保缓存强引用其键和值,防止被GC过早回收。    private static final Cache codeCache = Caffeine.newBuilder()            .expireAfterWrite(24, TimeUnit.HOURS) // 设置写入后24小时过期            // .maximumSize(10_000) // 可选:设置最大缓存条目数            .build();    private static int currentSendCount = 0; // 示例计数器    public void storeSmsData(Long id) {        SmsData data = new SmsData();        data.setSendCount(++currentSendCount);        data.setCheckCount(0);        codeCache.put(id, data);        System.out.println("Stored: id=" + id + ", data=" + data);    }    public SmsData getSmsData(Long id) {        SmsData retrievedData = codeCache.getIfPresent(id);        System.out.println("Retrieved: id=" + id + ", data=" + retrievedData);        return retrievedData;    }    public static void main(String[] args) throws InterruptedException {        CaffeineCacheService service = new CaffeineCacheService();        Long testId = 123L;        service.storeSmsData(testId);        SmsData data1 = service.getSmsData(testId); // 此时应该能获取到数据        // 模拟一段时间,但未到过期时间        Thread.sleep(100);        SmsData data2 = service.getSmsData(testId); // 仍然能获取到数据        // 假设另一个服务实例(但由于是static final,实际上是同一个缓存)        CaffeineCacheService anotherService = new CaffeineCacheService();        SmsData data3 = anotherService.getSmsData(testId); // 仍然能获取到数据    }}

2. 缓存的存取操作

在上述修正配置后,缓存的存取操作保持不变,但其行为将符合预期:

// 存储值SmsData dataToStore = new SmsData(); // 实例化 SmsDatadataToStore.setSendCount(++currentSendCount);dataToStore.setCheckCount(0);codeCache.put(id, dataToStore);// 获取值SmsData retrievedData = codeCache.getIfPresent(id);// 此时,只要 id 存在且未过期,retrievedData 将不再是 null

总结最佳实践点:

谨慎使用弱引用:除非你明确需要并且理解weakKeys()和weakValues()的垃圾回收行为,否则应避免使用它们。对于大多数应用场景,Caffeine的过期策略(expireAfterWrite、expireAfterAccess)和容量限制(maximumSize)足以管理缓存生命周期。确保缓存实例的单例性:对于应用程序全局使用的缓存,务必将其声明为static final,或者通过依赖注入框架(如Spring的@Bean)进行单例管理,确保在整个应用生命周期中只有一个缓存实例。理解Caffeine的驱逐策略:除了弱引用,Caffeine还提供了多种驱逐策略,如基于时间的(expireAfterWrite、expireAfterAccess)和基于容量的(maximumSize)。合理配置这些策略对于维护缓存的健康和性能至关重要。测试缓存行为:在开发过程中,对缓存的存取行为进行充分的单元测试和集成测试,以验证其是否按预期工作,尤其是在并发环境或长时间运行后。

总结

Caffeine缓存的强大功能伴随着一定的配置复杂性。当getIfPresent()意外返回null时,通常是由于对弱引用机制的误解导致缓存条目被垃圾回收,或缓存实例的生命周期管理不当导致数据存储在不同的缓存实例中。通过将缓存声明为static final并移除不必要的weakKeys()和weakValues()配置,可以有效解决这些问题,确保Caffeine缓存的稳定性和可靠性。理解这些核心概念对于构建健壮且高性能的Java应用程序至关重要。

以上就是解决Caffeine缓存意外返回Null:配置与生命周期最佳实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/571367.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
在Linux系统上使用CLion进行嵌入式C/C++开发的配置技巧
上一篇 2025年11月10日 06:13:52
Mac 键盘上的 Windows 按键映射
下一篇 2025年11月10日 06:13:56

相关推荐

  • 构建灵活的参数类型:使用 Builder 模式实现函数式编程

    构建灵活的参数类型:使用 Builder 模式实现函数式编程构建灵活的参数类型:使用 Builder 模式实现函数式编程构建灵活的参数类型:使用 Builder 模式实现函数式编程构建灵活的参数类型:使用 Builder 模式实现函数式编程

    本文介绍如何使用 Builder 模式来构建一个接受 Function 或 Float/Double 作为参数的函数,用于流式处理。通过 Builder 模式,可以避免方法重载带来的代码冗余,并提供一种优雅的方式来处理动态类型的输入,从而简化创意编码应用中的参数配置。 在函数式编程中,我们经常需要构…

    2026年9月29日 • 用户投稿
    000
  • 如何在Java中使用Vector类

    Vector是线程安全的动态数组,位于java.util包中,支持自动扩容;通过new Vector()创建,可用add()添加、get()获取、set()修改、remove()删除元素,支持增强for、迭代器或索引遍历;因同步开销大,性能低于ArrayList,多线程环境适用。 Java中的Vec…

    2026年9月29日
    000
  • 如何在SublimeText中设置代码对比工具?实现文件对比的教程

    如何在SublimeText中设置代码对比工具?实现文件对比的教程如何在SublimeText中设置代码对比工具?实现文件对比的教程如何在SublimeText中设置代码对比工具?实现文件对比的教程如何在SublimeText中设置代码对比工具?实现文件对比的教程

    最直接的方法是安装Diffy插件,通过Package Control安装后,可实现文件、选区或与磁盘文件的对比,操作直观高效,适合日常代码审查与差异追踪。 在Sublime Text中设置代码对比工具,最直接有效的方法通常是安装一个专门的插件,比如广受欢迎的 Diffy ,它能让你在编辑器内部直接进…

    2026年9月29日 • 用户投稿
    100
  • Linux环境变量机制的深度探究

    Linux环境变量机制的深度探究Linux环境变量机制的深度探究Linux环境变量机制的深度探究Linux环境变量机制的深度探究

    深入理解Linux环境变量机制,需要具体代码示例 Linux作为一种开放源代码的操作系统,具有广泛的应用场景和强大的定制能力,其中环境变量机制是其重要的特性之一。环境变量是在操作系统中定义的一种变量,用于保存系统中的信息,对于进程的运行和系统操作具有重要的作用。本文将深入探讨Linux环境变量的概念…

    2026年9月29日 • 用户投稿
    000
  • 如何利用数据压缩减少网络传输延迟?

    如何利用数据压缩减少网络传输延迟?如何利用数据压缩减少网络传输延迟?如何利用数据压缩减少网络传输延迟?如何利用数据压缩减少网络传输延迟?

    数据压缩能有效减少网络传输延迟,尤其适用于带宽受限或大数据传输场景。其核心原理是通过消除冗余信息缩小数据包体积,从而缩短传输时间。根据数据类型选择合适的压缩算法至关重要:文本常用gzip、deflate等无损压缩,图像可选JPEG、WebP,音频则用MP3、AAC,其中无损压缩保证数据完整,有损压缩…

    2026年9月29日 • 用户投稿
    100
  • PC版谷歌Play Games服务新功能 语音直接播放攻略

    PC版谷歌Play Games服务新功能 语音直接播放攻略PC版谷歌Play Games服务新功能 语音直接播放攻略PC版谷歌Play Games服务新功能 语音直接播放攻略PC版谷歌Play Games服务新功能 语音直接播放攻略

    谷歌近日宣布,其安卓游戏服务Google Play Games的PC版本正式上线。该平台允许用户在Windows设备上通过虚拟化技术运行安卓游戏,实现跨设备畅玩。目前,支持多平台同步的游戏库已收录超过20万款游戏。 此次发布的一大亮点是全新功能Sidekick。该功能以内置AI助手为核心,基于谷歌自…

    2026年9月29日 • 用户投稿
    100
  • 如何在SublimeText中设置项目管理?实现多项目切换的配置教程

    如何在SublimeText中设置项目管理?实现多项目切换的配置教程如何在SublimeText中设置项目管理?实现多项目切换的配置教程如何在SublimeText中设置项目管理?实现多项目切换的配置教程如何在SublimeText中设置项目管理?实现多项目切换的配置教程

    答案:通过保存和编辑.sublime-project文件实现项目管理,配置folders和settings定义项目结构与个性化设置,使用“Rebuild Index”解决索引问题,结合Git插件集成版本控制,备份项目文件及用户配置目录确保配置安全。 Sublime Text 的项目管理功能,能让你在…

    2026年9月29日 • 用户投稿
    100
  • Azure Blob 存储上传文件失败:权限问题排查与解决

    Azure Blob 存储上传文件失败:权限问题排查与解决Azure Blob 存储上传文件失败:权限问题排查与解决Azure Blob 存储上传文件失败:权限问题排查与解决Azure Blob 存储上传文件失败:权限问题排查与解决

    Azure Blob 存储上传文件时,有时会遇到“AuthorizationFailure: This request is not authorized to perform this operation”错误。这个错误通常表明您的应用程序没有足够的权限执行上传操作。本文将详细介绍如何排查和解决这…

    2026年9月29日 • 用户投稿
    100
  • Azure Blob 存储上传文件失败:权限错误排查与解决方案

    Azure Blob 存储上传文件失败:权限错误排查与解决方案Azure Blob 存储上传文件失败:权限错误排查与解决方案Azure Blob 存储上传文件失败:权限错误排查与解决方案Azure Blob 存储上传文件失败:权限错误排查与解决方案

    本文档旨在帮助开发者解决在使用 Azure Blob 存储上传文件时遇到的 “AuthorizationFailure” 错误,即权限不足的问题。文章将详细介绍该错误的常见原因,并提供通过配置 Azure 存储账户的网络防火墙规则,添加客户端 IP 地址来解决问题的具体步骤,…

    2026年9月29日 • 用户投稿
    000
  • PHP多维数组:高效提取嵌套结构中最后一个元素的特定值

    本文详细介绍了如何在PHP多维数组中,通过迭代和end()函数,准确获取特定嵌套层级下最后一个子数组中指定元素的值。教程提供了两种实现方式:直接输出和将值存储到新数组中,并强调了数据验证的重要性,以确保处理复杂或动态数据结构的健壮性。 1. 理解问题背景与数组结构 在处理复杂数据,尤其是通过解析xm…

    2026年9月29日
    000
  • VSCode如何实现智能代码审查 VSCodeAI辅助质量检测的配置方法

    vscode实现智能代码审查的核心是配置lint工具和ai辅助插件;2. 首先根据编程语言选择合适的lint工具(如eslint、pylint等),并在项目中安装工具及其vscode扩展;3. 然后通过配置文件(如.eslintrc.js)定义代码规则,并在vscode的settings.json中…

    2026年9月29日
    000
  • mysql数据库中数据备份与恢复概念

    数据备份与恢复是MySQL数据库安全的核心,通过物理或逻辑方式复制数据以防范丢失;全量、增量和差异备份各有优劣,需结合RPO与RTO制定策略;恢复时依类型选择对应方法,定期验证并保障存储安全,可有效提升系统容灾能力。 在MySQL数据库管理中,数据备份与恢复是保障数据安全的核心操作。当系统遭遇硬件故…

    2026年9月29日
    100
  • 谷歌发布最新 DORA 报告,揭示开发者如何使用 AI

    谷歌发布最新 DORA 报告,揭示开发者如何使用 AI谷歌发布最新 DORA 报告,揭示开发者如何使用 AI谷歌发布最新 DORA 报告,揭示开发者如何使用 AI谷歌发布最新 DORA 报告,揭示开发者如何使用 AI

    谷歌发布了最新的 2025 年 dora 报告,重点聚焦 ai 在软件开发中的广泛应用及其带来的深远影响。 DORA(DevOps Research and Assessment) 是由谷歌长期主导的开发效能研究项目,每年通过全球范围的大规模调研,为软件工程团队提供基于数据的洞察与实践指导。今年报告…

    2026年9月29日 • 用户投稿
    000
  • 使用Java在Vulkan中加载GLSL着色器

    使用Java在Vulkan中加载GLSL着色器使用Java在Vulkan中加载GLSL着色器使用Java在Vulkan中加载GLSL着色器使用Java在Vulkan中加载GLSL着色器

    本文介绍了如何在Java中使用Vulkan API加载和使用GLSL着色器。核心步骤是将GLSL着色器编译为SPIR-V二进制格式,然后加载到Vulkan管线中。通过使用ShaderSPIRVUtils等工具,可以简化编译过程,并确保着色器代码在Vulkan环境中正确执行。本文将提供详细的步骤和示例…

    2026年9月29日 • 用户投稿
    000
  • 如何在SublimeText中设置代码自动补全?提升编码效率的配置技巧

    如何在SublimeText中设置代码自动补全?提升编码效率的配置技巧如何在SublimeText中设置代码自动补全?提升编码效率的配置技巧如何在SublimeText中设置代码自动补全?提升编码效率的配置技巧如何在SublimeText中设置代码自动补全?提升编码效率的配置技巧

    Sublime Text的内置自动补全功能有限,需结合第三方插件如Anaconda或LSP实现智能补全。首先启用auto_complete并配置触发条件,再通过Package Control安装语言专属插件,如Python用Anaconda或LSP-pyright,JavaScript用TypeSc…

    2026年9月29日 • 用户投稿
    000
  • 夸克搜索怎么屏蔽不想要的内容_夸克搜索屏蔽不良内容设置教程

    夸克搜索怎么屏蔽不想要的内容_夸克搜索屏蔽不良内容设置教程夸克搜索怎么屏蔽不想要的内容_夸克搜索屏蔽不良内容设置教程夸克搜索怎么屏蔽不想要的内容_夸克搜索屏蔽不良内容设置教程夸克搜索怎么屏蔽不想要的内容_夸克搜索屏蔽不良内容设置教程

    关闭网页智能保护、启用成人模式、管理搜索历史、标记广告及开启内容拦截器可优化夸克搜索结果。具体:1. 在设置中调整【搜索与浏览】下的【网页智能保护】开关以控制跳转与广告过滤;2. 进入【隐私设置】完成年龄验证后选择是否开启【成人模式】来屏蔽敏感内容;3. 关闭【搜索历史记录提示】和【搜索发现】以减少…

    2026年9月29日 • 用户投稿
    200
  • 高通 CEO:AI 成为新的 UI,智能体构成新的操作系统

    高通 CEO:AI 成为新的 UI,智能体构成新的操作系统高通 CEO:AI 成为新的 UI,智能体构成新的操作系统高通 CEO:AI 成为新的 UI,智能体构成新的操作系统高通 CEO:AI 成为新的 UI,智能体构成新的操作系统

    在今日举行的骁龙峰会 2025 主题演讲中,高通公司总裁兼首席执行官克里斯蒂亚诺・阿蒙(cristiano amon)登台发表演讲,深入阐述了“ai everywhere”的未来愿景。 演讲中,阿蒙指出,我们正经历个人计算领域的一次深刻变革:人工智能正在演变为全新的用户界面(UI)。这一转变的核心在…

    2026年9月29日 • 用户投稿
    100
  • CentOS系统怎么查找软件包_yum-search命令使用技巧

    CentOS系统怎么查找软件包_yum-search命令使用技巧CentOS系统怎么查找软件包_yum-search命令使用技巧CentOS系统怎么查找软件包_yum-search命令使用技巧CentOS系统怎么查找软件包_yum-search命令使用技巧

    最常用方法是使用 yum search 命令,通过关键词搜索软件包,如 yum search java 可查找所有含“java”的包;2. 使用 yum provides 可定位命令所属包,如 yum provides ifconfig 能查出 net-tools;3. 结合 grep 过滤和 &#…

    2026年9月29日 • 用户投稿
    100
  • 使用蝴蝶号+AI工具,轻松实现智能直播带货

    使用蝴蝶号+AI工具,轻松实现智能直播带货使用蝴蝶号+AI工具,轻松实现智能直播带货使用蝴蝶号+AI工具,轻松实现智能直播带货使用蝴蝶号+AI工具,轻松实现智能直播带货

    直播带货效率可通过“蝴蝶号+ai工具”组合提升。1.蝴蝶号作为虚拟账号系统,可模拟真人操作,自动发言、点赞、刷礼物、发弹幕,营造直播间人气氛围,提高用户停留时间和转化率;2.ai工具则能写脚本、生成商品介绍、实时分析评论区情绪、语音播报促销信息,并实现自动回复评论、智能推荐话术、语音合成播报等功能,…

    2026年9月29日 • 用户投稿
    100
  • 安装系统时,遇到 “BIOS 设置与系统安装不兼容”,怎么调整?

    安装系统时,遇到 “BIOS 设置与系统安装不兼容”,怎么调整?安装系统时,遇到 “BIOS 设置与系统安装不兼容”,怎么调整?安装系统时,遇到 “BIOS 设置与系统安装不兼容”,怎么调整?安装系统时,遇到 “BIOS 设置与系统安装不兼容”,怎么调整?

    答案:BIOS设置与系统安装不兼容通常由启动模式、安全启动、硬盘模式等配置引起,需进入BIOS调整。首先检查Boot Mode,根据操作系统选择UEFI或Legacy BIOS;若安装Linux等非微软系统,可禁用Secure Boot;将SATA Mode设为AHCI以获得最佳性能,若驱动不支持可…

    2026年9月29日 • 用户投稿
    200

发表回复

登录后才能评论
关注微信