Reputation: 829
I want to be able to run the SAME scheduled job in Spring. After searching on the Internet, I figured out how to run multiple different jobs at the same time.
I have a @Service annotated class which has only one method, annotated with @Scheduled. I want to have multiple instances of this job running at the same time.
I am not using Quartz or Spring Batch( I have seen a lot of examples with Spring Batch).
The documentation doesn't clearly say if this can be achieved.
Upvotes: 3
Views: 3503
Reputation: 10596
Yes, it can be easily achieved, but not with @Scheduled
annotation.
How? Let me first explain how Spring works.
Spring from every method annotated with @Scheduled
creates a new Runnable
object and then schedules it for execution to the TaskScheduler
(ThreadPoolTaskScheduler
to be precise).
To see the exact code look at ScheduledAnnotationBeanPostProcessor.processScheduled()
.
So to fulfill your requirement: have multiple instances of the same job, but without using Quartz or Spring Batch we need to abandon @Scheduled
annotation and do something a bit different than what the ScheduledAnnotationBeanPostProcessor
does by default.
@Configuration
public class SpringConfig {
@Autowired
private TaskScheduler scheduler;
@Autowired
private YourServiceAnnotatedClass service;
@PostConstruct
public void startJobs() {
int numOfJobInstances = 3;
List<ImportantJob> jobs = IntStream.range(0, numOfJobInstances)
.mapToObj(i -> new ImportantJob("job" + i, service))
.collect(Collectors.toList());
jobs.forEach(this::schedule);
}
private void schedule(ImportantJob job) {
scheduler.schedule(job, new CronTrigger("*/5 * * * * *"));
// Above CronTrigger with 5 seconds was used, but feel free to use other variants, e.g.
// scheduler.scheduleAtFixedRate()
// scheduler.scheduleWithFixedDelay()
}
@Bean(destroyMethod = "shutdown")
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(3); // Adjust it to your needs
return taskScheduler;
}
}
class ImportantJob implements Runnable {
private final String name;
private final YourServiceAnnotatedClass service;
public ImportantJob(String name, YourServiceAnnotatedClass service) {
this.name = name;
this.service = service;
}
@Override
public void run() {
service.doSth();
}
}
As you can see, although @Scheduled
is useful and simple, it is not very flexible. But with some effort you can gain much more control over scheduled tasks.
Upvotes: 0