0

我知道 ShedLock 可以用来做与 Spring 集成的分布式锁:

    @Scheduled(cron = "*/5 * * * * ?")
    @SchedulerLock(name = "exampleLock", lockAtLeastForString = "20000", lockAtMostForString = "30000")
    private void exampleMethod(){
         System.out.println(String.format("[%s] test job runs...", new Date()));
}

但就我而言,我想执行从数据库中读取的多个计划任务(Crons),并由 ThreadPoolTask​​Scheduler 分别独立地进行处理。我编码如下,但是它不能处理多个实例来执行每个计划任务。Spring有没有办法实现这一点?任何想法将不胜感激。

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;
    }
}
4

2 回答 2

0

我终于找到了一种完成查询的方法。我可以使用自定义的 LockConfigurationExtractor 将 TaskScheduler 包装到 LockableTaskScheduler 并手动安排每个 taskScheduler,而不是使用 @SchedulerLock 注释:

DefaultLockManager defaultLockManager = new DefaultLockManager(lockProvider,
            customizedLockConfigurationExtractor);
return new LockableTaskScheduler(taskScheduler, defaultLockManager);
于 2019-09-26T06:26:53.093 回答
0

您可以创建一个 LockableTaskScheduler 对象并将其设置为 ScheduledTaskRegistrar。这将在每次执行之前检查 shedlock 表。

public LockableTaskScheduler getScheduler() {
    LockConfigurationExtractor lockConfigurationExtractor = (task) ->  Optional.
                of(new LockConfiguration(Instant.now(), "schedulerJob", Duration.ofMinutes(15), Duration.ofMinutes(5)));
        
        LockManager lockManager = new DefaultLockManager(lockProvider, lockConfigurationExtractor);
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("MyThreadPoolTaskScheduler");
        scheduler.initialize();
       return new LockableTaskScheduler(scheduler, lockManager);
}
于 2021-06-09T09:57:52.743 回答