ItemWriter的Spring Boot多线程

Posted

技术标签:

【中文标题】ItemWriter的Spring Boot多线程【英文标题】:Spring Boot Multiple threads for ItemWriter 【发布时间】:2021-11-07 22:40:18 【问题描述】:

我有一个包含两个主要步骤的 Spring Boot Batch 作业,第一个步骤是从电子表格中读取一堆行。第二个写入数据库。现在,它已设置为串行写入数据库

public CompositeItemWriter<SoftLayerData> compositeSoftlayerDataWriter(
    JpaItemWriter<SoftLayerData> softlayerDataWriter) 
  CompositeItemWriter<SoftLayerData> compositeWriter = new CompositeItemWriter<>();
  compositeWriter.setDelegates(asList(softlayerDataWriter));
  return compositeWriter;

问题是音量很大。由于没有理由维持任何秩序,我希望有多个作家。我试过这个:

final int writerCount = 10;
List<ItemWriter<? super SoftLayerData>> writers = new ArrayList<>(writerCount);
for(int counter=0;counter<writerCount;counter++) 
  writers.add(new JpaItemWriter<SoftLayerData>());

CompositeItemWriter<SoftLayerData> result = new CompositeItemWriter<>();
result.setDelegates(writers);
return result;

但我收到的是IllegalArgumentException: No EntityManagerFactory specified

我喜欢这种方法,但我怀疑我必须遵循一些非常复杂的 Spring Boot 方法。编写多个作家的最佳方法是什么?

谢谢, 樵夫

【问题讨论】:

是否需要两个步骤? step1 将项目写入哪里以及 step2 从哪里读取项目?为什么不使用单个面向块的步骤而不是两个步骤? 【参考方案1】:

CompositeItemWriter 调用委托编写器是顺序的,而不是并行的。因此,在复合编写器中创建 10 个 JpaItemWriters 作为委托不会使您的步骤多线程。

如果您希望该步骤变为多线程,则需要向其添加TaskExecutor,例如:

@Bean
public TaskExecutor taskExecutor() 
    return new SimpleAsyncTaskExecutor("spring_batch");


@Bean
public Step sampleStep(TaskExecutor taskExecutor) 
    return this.stepBuilderFactory.get("sampleStep")
                .<String, String>chunk(10)
                .reader(itemReader())
                .writer(itemWriter())
                .taskExecutor(taskExecutor)
                .build();

请参考Multi-Threaded step。

现在您的问题是您正在使用new 运算符创建JpaItemWriter,因此Spring 不会调用afterPropertiesSet 方法来检查强制属性。您需要在此作者上设置EntityManagerFactory

【讨论】:

我担心的是,我希望步骤的一个部分(即写作部分)的多个部分并行运行,而不仅仅是两个完整的步骤并行运行。让我们一次尝试10个。我不只是想建立一个包含 10 个项目的列表然后写。您上面的 sn-p 是否并行运行编写器? 答案中的样本是单步,不是两步,会被不同的线程并行执行。 我重构了我之前的批次以从上一步接收项目。原因是初始读者的分裂困难。您的上述解决方案将使用多少个线程?我是否需要复杂的分区代码来执行此操作? 我如何控制,甚至知道多线程步骤创建了多少线程? PS。我今天早些时候在 Youtube 上看到了你的视频。我不能对阅读器进行多线程处理,但我可以对编写器进行多线程处理。如何将项目从一个步骤传递到另一个步骤?寻找简单的内存解决方案。我可以向 VMware 付费以回答我的问题吗? 马哈茂德,感谢您的帮助;我接受了你的回答,因为它在很大程度上给了我想要的东西。我看了你的视频,并认为它为每个块提供了自己的线程。所以你的线程数粗略地说,是总项目数除以块大小。但是,我用 10 个项目进行了测试,它产生了 4 个线程。

以上是关于ItemWriter的Spring Boot多线程的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 如何使用多线程

多线程 Spring-boot 控制器方法

spring boot: 线程池ThreadPoolTaskExecutor, 多线程

Spring Boot 定时任务单线程和多线程

Spring Boot教程10——多线程

Spring Boot 中配置定时任务,实现多线程操作