【问题标题】:Keeping totals from each Spring Batch thread保持每个 Spring Batch 线程的总数
【发布时间】:2019-04-10 14:44:07
【问题描述】:

我正在实现一个执行一些数据库更新的 Spring 批处理应用程序。这里没有输入/输出文件,只是直接的数据库更新。

程序的布局如下:

  1. 准备 tasklet 调用一个 DB 过程来获取所有作业参数和需要完成的工作
  2. 工作被发送到分区器,工作被划分为线程
  3. 调用 tasklet 启动并在每个线程上调用以调用对数据库进行实际更新的不同过程
  4. 所有线程完成后,将调用“结束”过程来关闭所有数据库日志记录

我的问题在第 3 步和第 4 步之间。每个线程完成后,它会收集过程输出参数,其中一个是实际更新了多少工作。我希望能够保持所有线程的运行总数以及所有人完成了多少工作。然后,此信息将传递到第 4 步,该步骤会将这些总数包含到数据库日志记录表中。

目前,我将步骤 3 中过程的任何输出添加到 Map<String, String> resultMap 中,我可以看到每个线程的总数。我的问题是如何保持所有线程的总数被传递到第 4 步。

我尝试在 Invocation Tasklet 的顶部声明几个变量,这些变量将用于保持运行总计。问题是它们的值在每个线程之后被重置,即使我在从 Map 分配值时使用+=

public class SpringBatchInvocationTasklet  implements Tasklet, StepExecutionListener {

   int totalWork = 0;
   int totalWorkProcessed = 0;


    @Override
   public RepeatStatus execute(StepContribution arg0, ChunkContext chunkContext) throws Exception {
      Map<String, String> resultMap = SpringBatchDAO.process(workList, dbLogId, commitVal, userName, threadNo);

      totalWork += Integer.parseInt(resultMap.get(SpringBatchConstants.TOTAL_WORK));
      totalWorkProcessed += Integer.parseInt(resultMap.get(SpringBatchConstants.TOTAL_WORK_PROCESSED));

    }
}

总而言之,我需要能够获得所有线程的运行总数,以完成它们所做的工作,并将其传递给最终进程。

感谢您对此提供的任何帮助!

【问题讨论】:

    标签: java spring-batch


    【解决方案1】:

    根据您的设置,您的 tasklet 将由多个线程共享,因此它需要是线程安全的。

    问题是它们的值在每个线程之后被重置,即使我在从 Map 分配值时使用 +=

    += 运算符不是线程安全的,因为这不是原子操作。您需要在代码周围使用同步/锁定或使用线程安全的 Map 实现(如ConcurrentHashMap)和AtomicInteger(请参阅incrementAndGet 方法)而不是int 用于您的totalWorktotalWorkProcessed变量。

    以下问题/答案可能会有所帮助:Is the += operator thread-safe in Java?

    希望这会有所帮助。

    【讨论】:

    • 非常感谢马哈茂德。这正是问题所在,但我不是 100%。我最终使用了这个答案的一个版本stackoverflow.com/a/29884069/7829505,它非常适合我的需要。该变量现在正在正确更新。再次感谢您为我指明了正确的方向。
    • 太棒了!很高兴能帮上忙。
    猜你喜欢
    • 2015-02-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-13
    • 2021-05-07
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多