Reputation: 97
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)
Upvotes: 0
Views: 4206
Reputation: 124441
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.
Upvotes: 3