当前位置: 首页 > 知识库问答 >
问题:

有关使用 ShedLock 让 ThreadPoolTaskScheduler 处理多个计划任务的分布式锁的问题

沙宣
2023-03-14

我知道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 ),并由ThreadPoolTaskScheduler分别独立地处理。我编码如下,但是它不能处理多个实例来执行每个预定的任务。有没有什么有Spring或者没有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;
    }
}

共有2个答案

百里胜泫
2023-03-14

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

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);
}
井嘉胜
2023-03-14

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

DefaultLockManager defaultLockManager = new DefaultLockManager(lockProvider,
            customizedLockConfigurationExtractor);
return new LockableTaskScheduler(taskScheduler, defaultLockManager);
 类似资料:
  • 我已经创建了一个控制台应用程序,并尝试在任务计划程序中运行。当我通过单击可执行文件或使用快捷方式运行它时,它工作正常,但当我在任务调度程序中运行它时,我得到“PHLIP231 Prod的应用程序访问路径' C:\WINDOWS\DMBErrors '被拒绝。” 我已经在我的应用程序中搜索了此路径,甚至尝试手动将路径添加到我的计算机,但没有成功。我的应用程序构建了一个excel文件并将其写入相对于可

  • 但是我不能在一个计时器中处理不同的“计时器任务”。我试图将计时器任务对象添加到构造函数中,但是当我将新的计时器任务(RemindTask1)对象作为参数(内部类的实例)传递时,出现编译错误。 以下是它如何处理一项任务: 但是我完全被多个任务应该如何创建然后运行所困扰。 但是这不起作用,我不知道出了什么问题。当我将新的RemindTask2()作为参数传递时,我遇到了编译错误。

  • 我们有一个Spring Boot应用程序,并有计划的任务。 我们希望在多个服务器上部署我们的应用程序,因此将有多个应用程序实例。 如何将 Spring 配置为仅在指定的服务器上运行计划任务?

  • 我在我的Windows 2008 R2机器中安排了一个任务,但它未能触发日志中的以下错误(事件日志)。 错误: 任务计划程序无法启动用户“SAFFRON3\cb_admin”的“\Hyatt_International_Distribution”任务。其他数据:错误值:2147943645。 任务计划程序启动任务引擎""进程失败,原因是"LUAIsUpatedToken"中发生错误。命令="tas

  • 问题内容: 您将使用哪种分布式锁定服务? 要求是: 可以从不同的进程/机器看到的互斥(锁定) 锁定…释放语义 超时后自动释放锁-如果锁持有人死亡,它将在X秒后自动释放 Java实现 很高兴拥有:.Net实现 如果免费:死锁检测/缓解 易于部署,请参阅下面的注释。 我对诸如“可以通过数据库完成”或“可以通过JavaSpaces完成”之类的答案不感兴趣-我知道。我对现成的,现成的,经过验证的实现感兴趣

  • 我们有一个Spring+JPA web应用程序。我们使用两个tomcat服务器,它们运行两个应用程序并使用相同的数据库。 我们的应用程序requirmemnt之一是预形成cron调度任务。 谢了!