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

使用ExecutorService的submit方法处理列表记录仅最后一条生效如何解决

问题根因

你遇到的问题核心是重复使用了同一个Runnable实例:通过@Autowired注入的msnsfExecutorThread默认是Spring单例对象,整个循环过程中你反复给同一个对象的属性赋值,前一次赋值的结果会被后一次直接覆盖。等到线程池真正调度执行这个对象的run方法时,对象属性早就被改成了最后一条记录的值,自然只能读取到最后一条数据。

解决方案

方案1:每次循环创建新的Runnable实例

如果MsnsfExecutorThread不需要依赖Spring注入其他Bean,直接每次循环new新实例即可:

ExecutorService executor = Executors.newFixedThreadPool(3);
for (TempMSISDNCollectFee tempMSISDNCollectFee : list) {
    // 每次循环创建独立的执行对象,属性互不干扰
    MsnsfExecutorThread msnsfExecutorThread = new MsnsfExecutorThread();
    msnsfExecutorThread.setGcsAccountId(tempMSISDNCollectFee.getGcsAccountId());
    msnsfExecutorThread.setMsisdn(tempMSISDNCollectFee.getMsisdn());
    msnsfExecutorThread.setProcessStatus(tempMSISDNCollectFee.getProcessingStatus());
    msnsfExecutorThread.setPartnerCode(tempMSISDNCollectFee.getPartnerCode());
    executor.submit(msnsfExecutorThread);
}

如果MsnsfExecutorThread内部需要注入Spring容器中的其他Bean,无法直接new,可以将MsnsfExecutorThread的作用域改为原型模式,每次从Spring上下文获取新实例:

  1. 给MsnsfExecutorThread类增加原型作用域注解:
@Component
@Scope("prototype")
public class MsnsfExecutorThread implements Runnable {
    // 原有类逻辑保持不变
}
  1. 在使用类中注入ApplicationContext,每次循环获取新实例:
@Autowired
private ApplicationContext applicationContext;

// 执行逻辑部分
ExecutorService executor = Executors.newFixedThreadPool(3);
for (TempMSISDNCollectFee tempMSISDNCollectFee : list) {
    // 从Spring上下文获取全新的实例
    MsnsfExecutorThread msnsfExecutorThread = applicationContext.getBean(MsnsfExecutorThread.class);
    msnsfExecutorThread.setGcsAccountId(tempMSISDNCollectFee.getGcsAccountId());
    msnsfExecutorThread.setMsisdn(tempMSISDNCollectFee.getMsisdn());
    msnsfExecutorThread.setProcessStatus(tempMSISDNCollectFee.getProcessingStatus());
    msnsfExecutorThread.setPartnerCode(tempMSISDNCollectFee.getPartnerCode());
    executor.submit(msnsfExecutorThread);
}

方案2:改用局部变量传递参数

如果不想每次创建新的MsnsfExecutorThread实例,可以修改执行逻辑,不依赖成员变量存储参数,改用局部变量捕获每次循环的参数值:

ExecutorService executor = Executors.newFixedThreadPool(3);
for (TempMSISDNCollectFee tempMSISDNCollectFee : list) {
    // 提前提取当前循环的参数作为局部变量,lambda会捕获保留当前值
    String gcsAccountId = tempMSISDNCollectFee.getGcsAccountId();
    String msisdn = tempMSISDNCollectFee.getMsisdn();
    Integer processStatus = tempMSISDNCollectFee.getProcessingStatus();
    String partnerCode = tempMSISDNCollectFee.getPartnerCode();
    executor.submit(() -> {
        // 直接调用处理方法,把参数传入,不需要修改成员变量
        msnsfExecutorThread.process(gcsAccountId, msisdn, processStatus, partnerCode);
    });
}

同时给MsnsfExecutorThread新增接收参数的process方法,原有run方法的逻辑迁移到process方法中即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:06:04