使用分区程序Spring Batch限制线程

时间:2019-03-06 09:57:40

标签: spring spring-batch

我的Spring批处理应用程序消耗太多资源(+4转到Ram)。

当我查看jvm时,该应用程序会创建10个线程。

  • 我使用分区程序在没有调度程序的情况下按文件处理文件
  • jobExecutionListener用于在执行结束时停止批处理

    @Bean
    public Job mainJob() throws IOException {
    SimpleJobBuilder mainJob = this.jobBuilderFactory.get("mainJob")
                .start(previousStep())    
                .next(partitionStep())
                .next(finalStep())
                .listener(jobExecutionListener(taskExecutor()));;
        return mainJob.build();
    }
    
    @Bean
    public Step partitionStep() throws IOException {
        Step mainStep = stepBuilderFactory.get("mainStep")
                .<InOut, InOut>chunk(1)
                .reader(ResourceReader())
                .processor(processor())
                .writer(itemWriter())
                .build();
    
        return this.stepBuilderFactory.get("partitionStep")
                .partitioner(mainStep)
                .partitioner("mainStep", partitioner())
                .build();
    }
    
    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(1);
        taskExecutor.setMaxPoolSize(1);
        taskExecutor.setQueueCapacity(1);
        taskExecutor.setThreadNamePrefix("MyBatch-");
        taskExecutor.initialize();
    
        return taskExecutor;
    }
    
    //This jobExecutionListener stop the batch
    @Bean
    public JobExecutionListener jobExecutionListener(@Qualifier("taskExecutor") 
    ThreadPoolTaskExecutor executor) {
        return new JobExecutionListener() {
            private ThreadPoolTaskExecutor taskExecutor = executor;
            @Override
            public void beforeJob(JobExecution jobExecution) {
            }
    
            @Override
            public void afterJob(JobExecution jobExecution) {
                taskExecutor.shutdown();
                System.exit(0);
            }
        };
    }
    
    @Bean
    public Partitioner partitioner() {
        MultiResourcePartitioner partitioner = new MultiResourcePartitioner();
        ResourcePatternResolver patternResolver = new 
        PathMatchingResourcePatternResolver();
    
        try {
            partitioner.setResources(patternResolver.getResources(FILE + 
        configProperties.getIn()+ "/*.xml"));
        } catch (IOException e) {
            throw new RuntimeException("I/O problems when resolving the input file pattern.",e);
        }
        partitioner.setKeyName("file");
        return partitioner;
    }
    

如何在单线程中应用我的应用程序?任务执行程序不起作用。

1 个答案:

答案 0 :(得分:1)

您的应用创建了10个线程,但不一定是Spring Batch线程。根据您的配置,只应创建一个前缀为MyBatch-的线程。

此外,您将任务执行程序声明为Bean,但未在分区步骤中设置它。您的partitionStep应该类似于:

@Bean
public Step partitionStep() throws IOException {
   Step mainStep = stepBuilderFactory.get("mainStep")
        .<InOut, InOut>chunk(1)
        .reader(ResourceReader())
        .processor(processor())
        .writer(itemWriter())
        .build();

   return this.stepBuilderFactory.get("partitionStep")
        .step(mainStep) // instead of .partitioner(mainStep)
        .partitioner("mainStep", partitioner())
        .taskExecutor(taskExecutor())
        .build();
}
  

如何在单线程中应用我的应用程序?任务执行程序不起作用。

在分区步骤上设置任务执行器之后,您应该看到此步骤正在由ThreadPoolTaskExecutor中定义的唯一线程执行。但是,我看不到将单个线程用于分区步骤的好处,因为这种设置的通常目标是并行处理分区(在本地具有多个线程,或者在远程具有多个辅助JVM)。

作为旁注,最好在afterJob中用Job侦听器关闭任务执行器,但不要System.exit。您需要让JVM正常关闭。

希望这会有所帮助。