首页 > 解决方案 > Spring Batch Job 已完成,但它的线程从未被破坏

问题描述

我在春季批处理应用程序中有一项工作已成功完成,但完成后,它的线程进入等待状态。随着越来越多的作业实例被执行,tomcat 的线程数不断增加。

这是作业配置:

@Bean
@Scope("singleton")
@Qualifier(value = "job1")
public Job job() {
    return jobBuilderFactory.get("job1")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .preventRestart()
            .build();
}

@Bean
public Step step1() {
    return stepBuilderFactory.get("step1")
            .<Buylead, Buylead>chunk(10000)
            .reader(itemReader())
            .writer(itemWriter())
            .build();
}

public JdbcCursorItemReader<Buylead> itemReader() {
    JdbcCursorItemReader<Buylead> reader = new JdbcCursorItemReader<>();

    reader.setDataSource(dataSource);
    reader.setSql(" --- WHatever Query ----");
    reader.setRowMapper(new MapperBL());

    return reader;
}

public ItemWriter<Buylead> itemWriter(){
    FlatFileItemWriter<Buylead> itemWriter = new FlatFileItemWriter() ;

    itemWriter.setResource(new FileSystemResource("output/buyleadSolrDoc.xls"));
    itemWriter.setLineAggregator(new DelimitedLineAggregator<Buylead>() { {
                setFieldExtractor(new BeanWrapperFieldExtractor<Buylead>() { {
                    setNames(new String[] {*************** }); } }); } });
    itemWriter.setShouldDeleteIfEmpty(true);
    return itemWriter;
}

并且数据源保存在另一个配置类中。

是主要课程

@SpringBootApplication
@EnableBatchProcessing
public class Application  extends DefaultBatchConfigurer{

    public static void main(String[] args) {
        SpringApplication.run(SearchApplication.class, args);
    }
    
    @Override
    public void setDataSource(DataSource dataSource) {
        // override to do not set datasource even if a datasource exist.
        // initialize will use a Map based JobRepository (instead of database)
    }

}

作业正在成功执行。但它的线程进入等待状态。

是应用程序的 ThreadDump 部分

http-nio-8080-exec-2" #22 daemon prio=5 os_prio=0 cpu=0.11ms elapsed=29.43s tid=0x00007fcb6d6ddd60 nid=0xc724 waiting on condition  [0x00007fcae3ffe000]
   java.lang.Thread.State: WAITING (parking)
    at jdk.internal.misc.Unsafe.park(java.base@15.0.1/Native Method)
    - parking to wait for  <0x0000000713c00710> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(java.base@15.0.1/LockSupport.java:341)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@15.0.1/AbstractQueuedSynchronizer.java:505)
    at java.util.concurrent.ForkJoinPool.managedBlock(java.base@15.0.1/ForkJoinPool.java:3137)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@15.0.1/AbstractQueuedSynchronizer.java:1614)
    at java.util.concurrent.LinkedBlockingQueue.take(java.base@15.0.1/LinkedBlockingQueue.java:435)
    at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
    at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
    at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@15.0.1/ThreadPoolExecutor.java:1056)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@15.0.1/ThreadPoolExecutor.java:1116)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@15.0.1/ThreadPoolExecutor.java:630)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(java.base@15.0.1/Thread.java:832)*

请建议关闭处于 Park 状态的线程的方法。

标签: javaspringspring-bootspring-batch

解决方案


Spring Batch 不直接创建或管理线程。它将其委托给TaskExecutor不同地方的实现:

  • JobLauncher委托给任务执行器以启动作业
  • 委托给任务执行器StepBuilder以创建多线程步骤
  • FlowBuilder委托给任务执行器以创建拆分流并并行运行步骤
  • AsyncItemProcessor委托给任务执行器以在单独的线程中异步处理项目
  • TaskExecutorPartitionHandler委托给任务执行器以处理不同线程中的分区
  • ETC

在所有这些情况下,线程生命周期由底层TaskExecutor实现管理。如果您将任务执行器与 Spring Batch 一起使用,则需要确保它在不再需要时正确停止/关闭。从您分享的内容来看,您似乎没有在 Spring Batch 配置中使用任务执行器,因此您应该在应用程序上下文中的某个位置定义了一个未正确停止的任务执行器。


推荐阅读