Java spring批处理中多线程步骤和本地分区的区别是什么?
我有以下几点 有人提到: 1.1。多线程步骤启动并行处理的最简单方法是将TaskExecutor添加到步骤配置中 使用java配置时,可以将TaskExecutor添加到步骤中 如下例所示:Java spring批处理中多线程步骤和本地分区的区别是什么?,java,multithreading,spring-batch,partitioning,Java,Multithreading,Spring Batch,Partitioning,我有以下几点 有人提到: 1.1。多线程步骤启动并行处理的最简单方法是将TaskExecutor添加到步骤配置中 使用java配置时,可以将TaskExecutor添加到步骤中 如下例所示: @Bean 公共任务执行器任务执行器(){ 返回新的SimpleAsyncTaskExecutor(“spring_批”); } @豆子 公共步骤sampleStep(TaskExecutor TaskExecutor){ 返回此.stepBuilderFactory.get(“sampleStep”) .
@Bean
公共任务执行器任务执行器(){
返回新的SimpleAsyncTaskExecutor(“spring_批”);
}
@豆子
公共步骤sampleStep(TaskExecutor TaskExecutor){
返回此.stepBuilderFactory.get(“sampleStep”)
.chunk(10)
.reader(itemReader())
.writer(itemWriter())
.taskExecutor(taskExecutor)
.build();
}
上述配置的结果是,通过以下方式执行步骤:
读取、处理和写入每个项目块(每个提交
间隔)在单独的执行线程中。请注意,这意味着
要处理的项目没有固定的顺序,并且存在块
可能包含的项与
单螺纹外壳。除了任务设置的任何限制之外
执行器(例如它是否由线程池支持),存在
tasklet配置中的节流限制,默认为4。你
可能需要增加该值,以确保线程池已满
利用
但在我认为它应该通过局部分区来实现之前,我应该提供一个分区器来说明如何将数据划分为多个部分。多线程步骤应该自动完成
问题:
你能解释一下它是怎么工作的吗?除了线程编号之外,我如何管理它?它适用于平面锉刀吗
附笔。
我创建了一个示例:
@Configuration
public class MultithreadedStepConfig {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
private ToLowerCasePersonProcessor toLowerCasePersonProcessor;
@Autowired
private DbPersonWriter dbPersonWriter;
@Value("${app.single-file}")
Resource resources;
@Bean
public Job job(Step databaseToDataBaseLowercaseSlaveStep) {
return jobBuilderFactory.get("myMultiThreadedJob")
.incrementer(new RunIdIncrementer())
.flow(csvToDataBaseSlaveStep())
.end()
.build();
}
private Step csvToDataBaseSlaveStep() {
return stepBuilderFactory.get("csvToDatabaseStep")
.<Person, Person>chunk(50)
.reader(csvPersonReaderMulti())
.processor(toLowerCasePersonProcessor)
.writer(dbPersonWriter)
.taskExecutor(jobTaskExecutorMultiThreaded())
.build();
}
@Bean
@StepScope
public FlatFileItemReader csvPersonReaderMulti() {
return new FlatFileItemReaderBuilder()
.name("csvPersonReaderSplitted")
.resource(resources)
.delimited()
.names(new String[]{"firstName", "lastName"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}})
.saveState(false)
.build();
}
@Bean
public TaskExecutor jobTaskExecutorMultiThreaded() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// there are 21 sites currently hence we have 21 threads
taskExecutor.setMaxPoolSize(30);
taskExecutor.setCorePoolSize(25);
taskExecutor.setThreadGroupName("multi-");
taskExecutor.setThreadNamePrefix("multi-");
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}
@配置
公共类多线程StepConfig{
@自动连线
公共建筑商建筑商工厂;
@自动连线
公共StepBuilderFactory StepBuilderFactory;
@自动连线
专用ToLowerCepersonProcessor至LowerCepersonProcessor;
@自动连线
私人DbPersonWriter DbPersonWriter;
@值(“${app.single file}”)
资源;
@豆子
公共作业作业(步骤databaseToDataBaseLowercaseSlaveStep){
返回jobBuilderFactory.get(“myMultiThreadedJob”)
.incrementer(新的RunIdIncrementer())
.flow(csvToDataBaseSlaveStep())
(完)
.build();
}
私有步骤csvToDataBaseSlaveStep(){
返回stepBuilderFactory.get(“csvToDatabaseStep”)
.chunk(50)
.reader(csvPersonReaderMulti())
.处理器(ToLowerCepersonProcessor)
.writer(dbPersonWriter)
.taskExecutor(JobTaskExecutor多线程())
.build();
}
@豆子
@步进镜
公共FlatFileItemReader csvPersonReaderMulti(){
返回新的FlatFileItemReaderBuilder()
.名称(“CSVPersonReaderSplited”)
.资源
.delimited()
.names(新字符串[]{“firstName”,“lastName”})
.fieldSetMapper(新的BeanRapperFieldSetMapper(){{
setTargetType(Person.class);
}})
.saveState(false)
.build();
}
@豆子
公共TaskExecutor作业TaskExecutor多线程(){
ThreadPoolTaskExecutor taskExecutor=新的ThreadPoolTaskExecutor();
//目前有21个站点,因此我们有21个线程
taskExecutor.setMaxPoolSize(30);
taskExecutor.setCorePoolSize(25);
taskExecutor.setThreadGroupName(“multi-”);
taskExecutor.setThreadNamePrefix(“multi-”);
taskExecutor.AfterPropertieSet();
返回任务执行器;
}
}
根据日志,它确实有效,但我想知道细节。它比自编的分区器好吗?当您使用多线程步骤和分区时,这里有基本的区别 多线程步骤是单进程的,所以如果您已经为processor/writer保留了状态,那么使用它不是一个好主意。但是,如果您只是生成一个报告而不保存任何内容,那么这是一个不错的选择 正如您所提到的,假设您想要处理一个平面文件并将记录存储在DB中,那么您可以使用远程分块的概念,前提是您的阅读器不太重 Partitioner将为您可以使用逻辑划分的每组数据创建单独的进程
希望这能有所帮助。您所说的是远程分区。我说的是局部分区
@Configuration
public class MultithreadedStepConfig {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
private ToLowerCasePersonProcessor toLowerCasePersonProcessor;
@Autowired
private DbPersonWriter dbPersonWriter;
@Value("${app.single-file}")
Resource resources;
@Bean
public Job job(Step databaseToDataBaseLowercaseSlaveStep) {
return jobBuilderFactory.get("myMultiThreadedJob")
.incrementer(new RunIdIncrementer())
.flow(csvToDataBaseSlaveStep())
.end()
.build();
}
private Step csvToDataBaseSlaveStep() {
return stepBuilderFactory.get("csvToDatabaseStep")
.<Person, Person>chunk(50)
.reader(csvPersonReaderMulti())
.processor(toLowerCasePersonProcessor)
.writer(dbPersonWriter)
.taskExecutor(jobTaskExecutorMultiThreaded())
.build();
}
@Bean
@StepScope
public FlatFileItemReader csvPersonReaderMulti() {
return new FlatFileItemReaderBuilder()
.name("csvPersonReaderSplitted")
.resource(resources)
.delimited()
.names(new String[]{"firstName", "lastName"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}})
.saveState(false)
.build();
}
@Bean
public TaskExecutor jobTaskExecutorMultiThreaded() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// there are 21 sites currently hence we have 21 threads
taskExecutor.setMaxPoolSize(30);
taskExecutor.setCorePoolSize(25);
taskExecutor.setThreadGroupName("multi-");
taskExecutor.setThreadNamePrefix("multi-");
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}