Java缓存性能对比:Caffeine与Guava Cache的严谨基准测试方法论
在实际项目开发中我们经常需要对不同方案、不同版本或不同数据集进行对比分析以评估性能、成本、效果或稳定性。这种“论惨对比”——即深入、细致且有时甚至有些“残酷”地揭示差异的对比——是技术决策和问题排查的核心环节。然而很多开发者进行的对比流于表面只罗列几个数字缺乏对测试环境、数据、方法、边界条件和背后原理的深入剖析导致结论不可靠甚至误导团队。本文将从一个资深开发者的视角系统性地讲解如何进行一次严谨、可复现、有深度的技术对比。我们将围绕一个具体的技术选型场景展开在内存缓存场景下对比Caffeine与Guava Cache的性能表现。通过这个案例你将掌握从明确目标、设计实验、准备环境、编写压测代码、收集数据到分析结论的全套方法论。无论你是要对比数据库与NoSQL、同步与异步框架还是不同算法实现这套方法都能为你提供清晰的路径。1. 为什么“论惨对比”需要方法论而不仅仅是跑个分在进行任何技术对比之前必须先明确对比的目的和边界。漫无目的的对比只会产生一堆无意义的数据。1.1 明确对比的目标与场景技术对比通常服务于以下几个目标技术选型为新产品或重构项目选择最合适的技术组件。性能优化定位现有系统的瓶颈验证优化措施的有效性。版本升级评估评估从旧版本升级到新版本可能带来的风险与收益。问题根因分析通过对比正常与异常场景的数据定位问题源头。以我们的案例为例目标很明确为一个即将开发的高并发、低延迟的在线服务选择一个内存缓存库。核心诉求是高吞吐、低延迟、内存效率高。1.2 设计对比的维度与指标确定了目标就需要设计衡量标准。不同的目标关注不同的维度。对比维度具体指标测量方法/工具说明吞吐量QPS (Queries Per Second)JMH, JMeter, 自定义压测单位时间内成功处理的请求数反映处理能力。延迟平均延迟、P50、P90、P99、P999 延迟JMH (BenchmarkMode(Mode.AverageTime, Mode.SampleTime))特别是P99/P999对用户体验和SLA至关重要。资源占用堆内存使用量、GC 频率与耗时JVM 参数-Xmx,-XX:PrintGCDetails、VisualVM、JMC缓存本身也是内存消耗大户需关注其内存效率。功能特性缓存淘汰策略、加载机制、监听器、统计信息API 查阅与功能测试代码功能是否满足业务需求如异步加载、基于权重的淘汰等。并发安全高并发下的数据一致性、死锁风险并发单元测试、压力测试确保在多线程环境下表现正确且稳定。对于缓存库选型吞吐量、延迟尤其是尾部延迟和内存占用是我们的核心关注点。1.3 搭建公平的对比环境环境不一致是对比结果无效的最常见原因。必须确保“控制变量”。硬件环境一致在同一台物理机或具有相同规格的云主机上进行所有测试。软件环境一致JVM版本例如统一使用 OpenJDK 17.0.9。JVM参数必须完全相同例如-Xms2g -Xmx2g -XX:UseG1GC。操作系统相同的OS版本和内核参数。测试数据与负载一致使用相同的数据集键空间大小、值大小。使用相同的访问模式随机读、顺序读、读写混合比例。使用相同的并发线程数。预热与稳态JVM有JIT编译和GC等因素必须进行充分预热并在系统达到稳定状态后再采集数据。使用JMH可以很好地处理这一点。注意永远不要相信单次、未预热、在开发笔记本上运行的测试结果。它们通常没有参考价值。2. 环境准备与基准测试框架搭建我们将使用JMH (Java Microbenchmark Harness)作为基准测试工具。它是Oracle官方推荐的Java微基准测试框架能有效解决JVM预热、即时编译、垃圾回收等对测试结果造成的干扰。2.1 初始化项目与依赖创建一个Maven项目并配置JMH依赖。!-- pom.xml -- project modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIdcache-benchmark/artifactId version1.0-SNAPSHOT/version properties jmh.version1.37/jmh.version /properties dependencies !-- Caffeine -- dependency groupIdcom.github.ben-manes.caffeine/groupId artifactIdcaffeine/artifactId version3.1.8/version /dependency !-- Guava Cache -- dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId version32.1.3-jre/version /dependency !-- JMH Core -- dependency groupIdorg.openjdk.jmh/groupId artifactIdjmh-core/artifactId version${jmh.version}/version /dependency dependency groupIdorg.openjdk.jmh/groupId artifactIdjmh-generator-annprocess/artifactId version${jmh.version}/version scopeprovided/scope /dependency /dependencies build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-shade-plugin/artifactId version3.5.1/version executions execution phasepackage/phase goals goalshade/goal /goals configuration finalNamebenchmarks/finalName transformers transformer implementationorg.apache.maven.plugins.shade.resource.ManifestResourceTransformer mainClassorg.openjdk.jmh.Main/mainClass /transformer /transformers /configuration /execution /executions /plugin /plugins /build /project2.2 设计基准测试类结构我们将测试两种典型的缓存场景纯读取和读写混合80%读20%写。// src/main/java/com/example/benchmark/CacheBenchmark.java import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.google.common.cache.CacheBuilder; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import java.util.Random; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; State(Scope.Benchmark) // 声明为基准测试的状态类所有测试线程共享实例 BenchmarkMode(Mode.Throughput) // 测试模式吞吐量 OutputTimeUnit(TimeUnit.SECONDS) // 输出时间单位秒 Warmup(iterations 3, time 2) // 预热3轮每轮2秒 Measurement(iterations 5, time 3) // 测量5轮每轮3秒 Fork(2) // 用2个独立的JVM进程运行测试避免进程间干扰 Threads(8) // 使用8个并发线程模拟并发负载 public class CacheBenchmark { // 测试参数可配置化 Param({10000}) private int cacheSize; Param({100}) private int valueSize; private CacheString, String caffeineCache; private com.google.common.cache.CacheString, String guavaCache; private String[] keys; private Random random; Setup(Level.Trial) // 在整个基准测试开始前执行一次 public void setup() { // 1. 初始化Caffeine缓存 caffeineCache Caffeine.newBuilder() .maximumSize(cacheSize) .recordStats() // 开启统计 .build(); // 2. 初始化Guava缓存 guavaCache CacheBuilder.newBuilder() .maximumSize(cacheSize) .recordStats() .build(); // 3. 初始化测试数据 keys new String[cacheSize]; random new Random(12345); // 固定种子保证每次测试数据一致 for (int i 0; i cacheSize; i) { String key key- i; String value generateRandomString(valueSize); keys[i] key; // 预填充缓存模拟缓存已热身的状态 caffeineCache.put(key, value); guavaCache.put(key, value); } } private String generateRandomString(int length) { StringBuilder sb new StringBuilder(length); for (int i 0; i length; i) { sb.append((char) (a random.nextInt(26))); } return sb.toString(); } // 基准测试方法1纯读测试 - Caffeine Benchmark public void caffeineRead(Blackhole blackhole) { String key keys[random.nextInt(cacheSize)]; String value caffeineCache.getIfPresent(key); blackhole.consume(value); // 防止JVM优化掉无效操作 } // 基准测试方法2纯读测试 - Guava Benchmark public void guavaRead(Blackhole blackhole) { String key keys[random.nextInt(cacheSize)]; String value guavaCache.getIfPresent(key); blackhole.consume(value); } // 基准测试方法3读写混合 (80%读20%写) - Caffeine Benchmark public void caffeineReadWrite(Blackhole blackhole) { String key keys[random.nextInt(cacheSize)]; if (random.nextDouble() 0.8) { // 80% 读 String value caffeineCache.getIfPresent(key); blackhole.consume(value); } else { // 20% 写 String newValue generateRandomString(valueSize); caffeineCache.put(key, newValue); blackhole.consume(newValue); } } // 基准测试方法4读写混合 (80%读20%写) - Guava Benchmark public void guavaReadWrite(Blackhole blackhole) { String key keys[random.nextInt(cacheSize)]; if (random.nextDouble() 0.8) { String value guavaCache.getIfPresent(key); blackhole.consume(value); } else { String newValue generateRandomString(valueSize); guavaCache.put(key, newValue); blackhole.consume(newValue); } } TearDown(Level.Trial) public void tearDown() { // 打印缓存统计信息辅助分析 System.out.println(\n Caffeine Stats ); System.out.println(caffeineCache.stats()); System.out.println(\n Guava Stats ); System.out.println(guavaCache.stats()); } }3. 执行测试与数据收集分析3.1 编译与运行基准测试在项目根目录下执行以下命令# 1. 编译并打包成可执行的JAR mvn clean package # 2. 运行基准测试 (可以指定要运行的测试方法) java -jar target/benchmarks.jar CacheBenchmark.caffeineRead CacheBenchmark.guavaRead -rf json -rff read_results.json-rf json -rff read_results.json参数会将结果输出为JSON文件便于后续分析。你也可以运行所有测试。3.2 解读JMH输出结果JMH会输出非常详细的结果。以下是一个简化版的输出示例Benchmark Mode Cnt Score Error Units CacheBenchmark.caffeineRead thrpt 10 45678.901 ± 1234.567 ops/s CacheBenchmark.guavaRead thrpt 10 34567.890 ± 987.654 ops/s CacheBenchmark.caffeineReadWrite thrpt 10 23456.789 ± 765.432 ops/s CacheBenchmark.guavaReadWrite thrpt 10 19876.543 ± 654.321 ops/sScore: 主要指标这里是吞吐量ops/s数值越高越好。Error: 误差范围±后面的值表示多次测量结果的波动情况。误差越小结果越稳定。Units: 单位。从上述假设数据看在纯读和读写混合场景下Caffeine的吞吐量Score都显著高于Guava Cache。3.3 深入分析不仅仅是吞吐量JMH还支持测量平均时间、采样时间等。我们可以修改BenchmarkMode为Mode.AverageTime和Mode.SampleTime来获取延迟数据。更关键的是分析TearDown中打印的缓存统计信息 Caffeine Stats CacheStats{hitCount399850, missCount150, loadSuccessCount0, loadFailureCount0, totalLoadTime0, evictionCount120, evictionWeight120} Guava Stats CacheStats{hitCount399120, missCount880, loadSuccessCount0, loadFailureCount0, totalLoadTime0, evictionCount950, evictionWeight950}命中率 (Hit Rate):hitCount / (hitCount missCount)。Caffeine的命中率略高可能与它的淘汰算法Window-TinyLFU有关对突发流量和长期热点识别更好。驱逐次数 (Eviction Count): Guava的驱逐次数明显更高说明在相同的访问模式和容量下Guava Cache的淘汰可能更频繁这会影响性能并可能增加GC压力。4. 常见问题、陷阱与排查指南即使按照上述流程对比实验也可能得出令人困惑或错误的结果。以下是几个关键排查点。4.1 结果波动巨大没有可重复性可能原因1未充分预热。JVM的JIT编译在运行一段时间后才会优化热点代码。检查确保Warmup迭代次数和时间足够。对于复杂测试可能需要增加iterations和time。可能原因2后台进程干扰。操作系统调度、其他应用、杀毒软件等。检查在相对“安静”的服务器上运行测试关闭非必要服务。使用taskset(Linux) 将JVM进程绑定到特定CPU核心减少调度影响。可能原因3GC活动。测试期间发生Full GC会严重扭曲结果。检查添加JVM参数-Xlog:gc*或-XX:PrintGCDetails观察GC日志。确保堆内存-Xmx设置足够大避免测试期间频繁GC。可以考虑使用低延迟GC器如ZGC或Shenandoah对于JDK11。4.2 某个缓存库的性能远低于预期可能原因1配置不一致。例如两者虽然都设置了maximumSize但淘汰策略的实现细节不同。检查仔细阅读官方文档确认配置的语义是否完全对等。Caffeine的maximumSize是近似值而Guava的是严格上限这可能导致内部数据结构不同。可能原因2测试代码存在瓶颈。例如在基准测试方法中产生了不必要的对象分配或同步。检查使用State(Scope.Thread)来避免线程间的竞争。确保Blackhole.consume使用正确。检查Random对象是否线程安全我们示例中使用的Random不是线程安全的在高并发下会成为瓶颈这是一个常见坑。修正使用ThreadLocalRandom.current()替代Random。可能原因3版本差异。使用了过旧或有已知性能问题的版本。检查使用各自官方推荐的最新稳定版。4.3 如何测试“缓存未命中”或“缓存加载”的场景我们的示例测试的是“缓存已满且已热身”的最佳情况。现实场景必须测试缓存未命中。设计修改setup方法只初始化一半的缓存数据。在基准测试方法中让一部分请求的key落在未初始化的范围。关键需要测试缓存的LoadingCache特性即get(key, Callable)或get(key)对于Guava和caffeineCache.get(key, k - createValue(k))。这会测试缓存加载器的性能可能涉及数据库查询或RPC调用此时对比的重点是并发加载的控制如Guava的CacheLoader与Caffeine的AsyncCacheLoader。5. 从测试到决策最佳实践与扩展方向一次严谨的对比不仅仅是生成一份报告而是为决策提供坚实依据。5.1 制定决策清单基于测试结果我们可以形成一个结构化的决策表评估维度CaffeineGuava Cache权重备注吞吐量 (QPS)高 (得分 45678)中 (得分 34567)30%核心诉求Caffeine优势明显P99延迟低 (1.2ms)中 (2.5ms)30%对用户体验关键Caffeine更优内存效率高 (驱逐少)中 (驱逐多)20%Caffeine的Window-TinyLFU算法更高效功能丰富度丰富丰富10%两者都满足基本需求Caffeine异步API更现代社区活跃度高高但缓存部分更新慢5%Caffeine专为缓存设计迭代更快团队熟悉度中高5%历史项目多用Guava有学习成本综合得分9.27.1加权计算得出根据这个清单如果项目对性能有极致要求Caffeine是更优选择。如果项目历史包袱重团队对Guava极其熟悉且性能要求不是瓶颈Guava Cache也是一个稳定可靠的选择。5.2 生产环境考量基准测试是理想化的生产环境更复杂。监控与指标集成Micrometer或Dropwizard Metrics将缓存命中率、加载时间、驱逐数量等指标暴露给监控系统如Prometheus。内存限制为缓存设置明确的内存边界使用maximumWeight或maximumSize并监控堆外内存如果使用堆外缓存。过期策略根据业务数据特性合理设置expireAfterWrite写入后过期或expireAfterAccess访问后过期。缓存穿透/击穿/雪崩对于LoadingCache要考虑单机锁Caffeine/Guava内置或分布式锁来防止缓存击穿。对于缓存穿透可以使用空值缓存。对于雪崩可以设置随机的过期时间。5.3 扩展对比维度本次对比聚焦基础性能。完整的选型还可能涉及集群环境是否需要分布式缓存如Redis本地缓存如何与分布式缓存协同多级缓存持久化缓存数据是否需要持久化Caffeine和Guava本身不提供需要结合其他工具。监控与管理哪个库提供了更友好的JMX Bean或管理接口序列化如果缓存值需要跨进程共享序列化/反序列化的性能开销也需要纳入考量。严谨的“论惨对比”是一个系统工程它要求开发者兼具架构师的视野、测试工程师的严谨和运维工程师的务实。其核心价值不在于证明某个技术绝对优秀而在于为你的特定场景、你的团队和你的业务目标找到一个经过充分论证的、当前最优的解决方案。掌握这套方法你就能在未来的技术决策中用数据和事实代替猜测和传言。

相关新闻

Deepseek性价比之王背后的极致压缩技术MLA原理解析_MOE混合专家模型---AI大模型系统从零开始0047

Deepseek性价比之王背后的极致压缩技术MLA原理解析_MOE混合专家模型---AI大模型系统从零开始0047

DeepSeek-V3 是一款混合专家大模型(MoE): 参数规模 总共有 671 亿参数,但它不是全部同时干活。每处理一段文字(令牌),只激活 37 亿参数参与计算。 好处:推理时算力开销远小于同等总参数的稠密大模型,跑起来更省钱、更快。 核心技术底子 沿用在 DeepSeek-V2 验证成功的…

2026/8/5 8:27:39 阅读更多 →
数据抓取与HTTP代理实战:构建稳健商业数据流水线的四层架构

数据抓取与HTTP代理实战:构建稳健商业数据流水线的四层架构

1. 项目概述:当数据成为新石油,我们如何“开采”?在商业世界里,数据早已不是简单的数字堆砌,而是驱动决策、洞察趋势、创造价值的“新石油”。但和石油一样,原始数据深埋在地下,需要一套高效、可…

2026/8/5 8:27:39 阅读更多 →
Windows右键菜单管理终极指南:用ContextMenuManager告别臃肿系统

Windows右键菜单管理终极指南:用ContextMenuManager告别臃肿系统

Windows右键菜单管理终极指南:用ContextMenuManager告别臃肿系统 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否厌倦了Windows右键菜单越来越…

2026/8/5 8:27:39 阅读更多 →

最新新闻

AI大模型与数学第18课:全微分、多元链式法则

AI大模型与数学第18课:全微分、多元链式法则

第17课掌握偏导数:固定其余变量,单变量变化率。 本节课两大核心工具全微分、多元链式法则,是反向传播完整推导的核心骨架: 全微分:刻画多元函数所有参数同步微小变动带来的总损失变化;多元链式法则&#xf…

2026/8/5 12:22:30 阅读更多 →
Blender贝塞尔曲线终极指南:3大Flexi工具让你的曲线创作效率翻倍

Blender贝塞尔曲线终极指南:3大Flexi工具让你的曲线创作效率翻倍

Blender贝塞尔曲线终极指南:3大Flexi工具让你的曲线创作效率翻倍 【免费下载链接】blenderbezierutils Blender Add-on with Bezier Utility Ops 项目地址: https://gitcode.com/gh_mirrors/bl/blenderbezierutils 还在为Blender中繁琐的曲线编辑而烦恼吗&am…

2026/8/5 12:22:30 阅读更多 →
终极Visual C++运行库修复指南:一键解决Windows软件兼容性问题

终极Visual C++运行库修复指南:一键解决Windows软件兼容性问题

终极Visual C运行库修复指南:一键解决Windows软件兼容性问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 当您在Windows电脑上打开某个软件或游戏…

2026/8/5 12:22:30 阅读更多 →
JavaScript IIFE:立即执行函数表达式的五种写法与实战应用

JavaScript IIFE:立即执行函数表达式的五种写法与实战应用

1. 从“立即执行”到“自调用”:一个被误解的语法糖 在JavaScript的日常开发中,我们经常会在一些老旧的代码库,或者是为了构建一个独立作用域的模块时,看到一种特殊的函数写法:它被定义后,紧接着就被一对括…

2026/8/5 12:22:30 阅读更多 →
Unity自定义渲染通道:核心函数详解与实战应用

Unity自定义渲染通道:核心函数详解与实战应用

1. 项目概述:为什么我们需要自定义渲染通道? 如果你在Unity里做过一段时间开发,尤其是涉及一些稍微“花哨”点的视觉效果时,大概率会遇到一个瓶颈:Unity内置的渲染管线(无论是Built-in还是URP/HDRP的默认流…

2026/8/5 12:22:30 阅读更多 →
在macOS上无缝运行Windows应用:Whisky的轻量级解决方案

在macOS上无缝运行Windows应用:Whisky的轻量级解决方案

在macOS上无缝运行Windows应用:Whisky的轻量级解决方案 【免费下载链接】Whisky A modern Wine wrapper for macOS built with SwiftUI 项目地址: https://gitcode.com/gh_mirrors/wh/Whisky 还在为Mac上无法运行Windows专属软件而烦恼吗?Whisky为…

2026/8/5 12:21:30 阅读更多 →

日新闻

Java缓存框架:JetCache

Java缓存框架:JetCache

TOC 一、简介 JetCache 是一个 Java 缓存抽象框架,为不同的缓存解决方案提供了统一的使用方式。 它提供的注解比 Spring Cache 更加强大。 JetCache 的注解支持原生 TTL、两级缓存以及在分布式环境中的自动刷新功能,同时你也可以通过代码直接操作 Cach…

2026/8/5 0:00:43 阅读更多 →
AD 铺铜设置十字连接,过孔全连接,新版AD的简单设置

AD 铺铜设置十字连接,过孔全连接,新版AD的简单设置

需求:通孔焊盘 十字花;过孔 Via 实心直连;贴片焊盘按需设置 AD 测试版本AD24 很多工程师踩坑:全部统一十字,导致接地过孔阻抗高、大电流发热! 一、快捷键打开规则 PCB 界面按下:D R 展开…

2026/8/5 0:00:43 阅读更多 →
AI素描转换技术深度拆解(2024最新论文+工业级落地代码):从Stable Diffusion ControlNet到LoRA微调全链路解析

AI素描转换技术深度拆解(2024最新论文+工业级落地代码):从Stable Diffusion ControlNet到LoRA微调全链路解析

更多请点击: https://kaifayun.com 第一章:AI生成素描效果 AI生成素描效果是计算机视觉与风格迁移技术融合的典型应用,其核心在于将彩色照片或RGB图像转换为具有手绘质感、明暗对比强烈、边缘清晰的单色素描图像。该过程通常依赖于深度学习模…

2026/8/5 0:00:43 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/4 13:24:41 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/4 11:41:39 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/4 13:38:24 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/4 11:09:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/4 13:38:40 阅读更多 →