I know ShedLock could be used to do distributed lock integrated with Spring as:
@Scheduled(cron = "*/5 * * * * ?")
@SchedulerLock(name = "exampleLock", lockAtLeastForString = "20000", lockAtMostForString = "30000")
private void exampleMethod(){
System.out.println(String.format("[%s] test job runs...", new Date()));
}
But for my case I'd like to execute multiple schedule tasks(Crons) read from Database and process by ThreadPoolTaskScheduler separately and independently. I coded as below, however it doesn't work dealing with multiple instances to execute each scheduled task. Is there any way with Spring or without to achieve this? Any thought will be highly appreciated.
public class ExampleShedLock implements SchedulingConfigurer {
@Resource
private ScheduleTaskRepository scheduleTaskRepository;
@Resource
private TaskScheduler threadPoolTaskScheduler;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setTaskScheduler(getThreadPoolTaskScheduler());
Map<String, String> dataMap = scheduleTaskRepository
.selectExpressionByIsActive();
dataMap.forEach(
(key, expression) -> scheduledTaskRegistrar.getScheduler()
.schedule(() -> scheduledTask(),
(TriggerContext triggerContext) -> {
CronTrigger trigger = new CronTrigger(
expression,
TimeZone.getTimeZone(ZoneOffset.UTC));
return trigger.nextExecutionTime(triggerContext);
}));
}
@SchedulerLock(name = "TaskScheduler",
lockAtLeastFor = 20*1000, lockAtMostFor = 30*1000)
private void scheduledTask() {
System.out.println(
Thread.currentThread().getName() + " - " + Calendar
.getInstance()
.getTime();
}
@Bean(name = "threadPoolTaskScheduler")
public TaskScheduler getThreadPoolTaskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
taskScheduler.setThreadNamePrefix("Scheduled-");
taskScheduler.setRejectedExecutionHandler(new
ThreadPoolExecutor.CallerRunsPolicy());
taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
taskScheduler.setAwaitTerminationSeconds(60);
taskScheduler.initialize();
return taskScheduler;
}
}
I finally figure out one way to accomplish the query. Rather than to use @SchedulerLock annotation, I could wrap the TaskScheduler to LockableTaskScheduler with your customized LockConfigurationExtractor and schedule each taskScheduler manually like this:
DefaultLockManager defaultLockManager = new DefaultLockManager(lockProvider,
customizedLockConfigurationExtractor);
return new LockableTaskScheduler(taskScheduler, defaultLockManager);