You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无限链式调用的CompletableFuture是否会被垃圾回收?

问题结论

首先你的无限链式实现本身不会因为thenCompose的链式引用导致旧CompletableFuture无法回收,真正存在内存风险的点是你代码里的全局eventFutureMap,以及未处理的线程安全问题。

原理说明
  • JDK的CompletableFuture的依赖引用仅在前置任务未完成时存在:当你通过existingEvent.thenCompose()生成新的eventFuture后,一旦existingEvent执行完成、回调逻辑执行完毕,新的eventFuture会主动清除对existingEvent的引用,不会持有整条链式的所有历史节点。
  • 旧的CompletableFuture在完成、且被eventFutureMap移出引用后,没有任何强引用指向它,会被GC正常回收,哪怕你已经串了上万个链式节点也不会残留。
你代码存在的两个核心问题

1. 线程安全隐患

你当前用的HashMap是非线程安全的,多线程并发调用publish()方法时,get和put操作存在竞态条件,轻则丢失链式更新导致事件顺序不保证,重则触发HashMap扩容死循环导致服务挂死,建议直接替换为ConcurrentHashMap。

2. 全局Map的冷key内存泄漏

你每次都会把最新的CompletableFuture存入eventFutureMap,如果某个key后续很长时间没有新事件进入,该key对应的最后一个CompletableFuture会被Map一直强持有,永远无法被回收,当冷key数量多了之后就会引发内存泄漏。

优化方案

在生成eventFuture之后追加完成回调,判断当前Map中存储的是否还是当前这个CompletableFuture:如果是,说明该key暂时没有新事件进入,可以直接移除key释放引用,不会影响后续新事件的顺序保证。
优化后代码示例:

// 替换为线程安全的ConcurrentHashMap
Map<Integer, CompletableFuture<EventResult>> eventFutureMap = new ConcurrentHashMap<>();

Publisher publisher;
    
public CompletableFuture<EventResult> publish(Event event) {
    Integer key = event.getKey();
    CompletableFuture<EventResult> existingEvent = eventFutureMap.get(key);
    CompletableFuture<EventResult> eventFuture;
    if (existingEvent != null) {
        eventFuture = existingEvent.thenCompose(meta -> publisher.publish(event));
    } else {
        eventFuture = publisher.publish(event);
    }
    // 追加完成回调,无新事件时自动清理key
    eventFuture.whenComplete((res, throwable) -> {
        // 只有当前Map中存储的还是自己的时候才清理,避免误删新提交的任务
        eventFutureMap.remove(key, eventFuture);
    });
    eventFutureMap.put(key, eventFuture);
    return eventFuture;
}

注意ConcurrentHashMap的remove(key, value)是原子操作,不需要额外加锁,只有当key对应的值完全等于传入的value时才会删除,完美避免误删新提交的后续事件任务。

补充验证

你可以通过添加虚引用监控,或者本地压测后dump内存分析,确认已经完成的旧CompletableFuture不会残留,只有未完成的任务和Map中暂存的最新任务会被持有。

内容的提问来源于stack exchange,提问作者James Hp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:54:01