简体   繁体   中英

How to run the same @Scheduled method in Spring Boot in multiple threads

I currently have a @Scheduled method in my Spring Boot app

   @Async
    @Scheduled(fixedDelay = 2000, initialDelay = 1000)
    public void taskA() throws InterruptedException {
        System.out.println("A - " + Thread.currentThread().getName());
    }

My Spring Application file is as follows: @SpringBootApplication

@EnableAsync
@EnableScheduling
public class SpringScheduleApplication {

    public static void main(String[] args) {

        SpringApplication.run(SpringScheduleApplication.class, args);
    }


}

I also have a config class set up to establish a thread pool to allow for parallel jobs

@Configuration
@EnableScheduling
public class SchedulingConfig implements SchedulingConfigurer {
    public static final int NUM_PROCESSING_WORKERS = 10;
    @Override
    public void configureTasks(
            ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(NUM_PROCESSING_WORKERS);
    }
}

When I run the scheduler, I can clearly see the job is picking up in the multiple thread pools.

A - pool-1-thread-7
A - pool-1-thread-3
A - pool-1-thread-9
....

Ok..... so here's my problem

What I WANT to do is create multiple instances of taskA and have that run in N amount of threads.

I know I can create N amount of methods with the @Scheduled annotation performing the same logic, but this is NOT an acceptable solution. This seems very redundant and looks bad, and don't want to copy paste if I add another thread to the pool. I want to be able to say something like:

for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
  taskA(); // I just want N amount of this tasks existing in parallel.
}

I cannot use anything like Quartz Scheduler because I want to be able to continue to use @Autowired in my project (I can get this behavior to work in Quartz, but setting up @Autowired is a pain and I would like to work with Spring Schedule annotations as much as possible)

You already wrote the answer yourself. You already have the for loop to use. Put the @Scheduled on the method with the for-loop, which calls a taskA method in an external class, and which has the @Async annotation.


@Autowired
private External external

@Scheduled
public void scheduler() {
  for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
    external.taskA(); // I just want N amount of this tasks existing in parallel.
  }
}
public class External {


  @Async
  public void taskA() { ... }

}

Another solution is to inject the AsyncTaskExecutor into your class that does the scheduling and call submit to execute the task.

@Autowired
private AsyncTaskExecutor taskExecutor;

@Scheduled
public void scheduler() {
  for(int i = 0; i < SchedulingConfig.NUM_PROCESSING_WORKERS; i++){
    taskExecutor.submit( () -> taskA());  
  }
}

The advantage of this is that it is more explicit and that your taskA method can be in the same class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM