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

Spring Boot中CompletableFuture allOf合并结果出现重复与缺失问题

问题分析与解决方案

结论

合并结果环节不会导致重复或缺失,问题根源在@Async方法中的共享可变对象。

具体问题点

你的@Async方法中使用的unitaConversioneInXml如果是类的成员变量(而非方法局部变量),会被多个异步线程共享并发修改:

  • 当线程A正在生成某条rigaQ对应的XML时,线程B可能已经修改了unitaConversioneInXml的RecordTypeQ值,导致线程A最终生成的XML使用了线程B的参数,出现重复。
  • 并发修改还可能导致部分rigaQ的参数被覆盖,对应的XML直接缺失。

另外,你在方法内使用Collections.synchronizedList是多余的——因为每个异步任务的循环是单线程串行执行的,普通ArrayList完全足够,同步列表反而会带来不必要的性能开销。

修复代码

将unitaConversioneInXml改为方法局部变量,让每个异步任务拥有独立的实例:

@Async
public CompletableFuture<List<byte[]>> genereteXmlsWithMultithreading(RigheCorrelate righeCorrelate) {
    // 每个任务创建独立的转换实例,避免线程间状态污染
    UnitaConversioneInXml unitaConversioneInXml = new UnitaConversioneInXml();
    
    unitaConversioneInXml.setRecordTypeANABI((RecordTypeANABI) serialize(righeCorrelate.getRigaANABI()));
    unitaConversioneInXml.setRecordTypeT07((RecordTypeTypeT) serialize(righeCorrelate.getRigaT()));

    List<byte[]> xmlFilesPerTask = new ArrayList<>();
    for (String rigaQ : righeCorrelate.getRigheQ()) {
        unitaConversioneInXml.setRecordTypeQ((RecordTypeTypeQ) serialize(rigaQ));
        try {
            xmlFilesPerTask.add(XmlUtils.generateXml(unitaConversioneInXml.mapToXmlClass(), jaxbContext));
        } catch (JAXBException e) {
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Errore nella generazione di un file xml", e);
        }
    }

    log.info("Elaborati {} xmls", xmlFilesPerTask.size());
    return CompletableFuture.completedFuture(xmlFilesPerTask);
}

额外检查项

  1. 确认jaxbContext是线程安全的:JAXBContext本身是线程安全的,可放心共享。
  2. 确认serialize方法无共享状态:如果该方法依赖类成员变量或其他共享资源,需确保其线程安全。

内容的提问来源于stack exchange,提问作者Saverio Mirko Viola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:12:45