你如何配置Spring以执行重叠的fixedRate任务?

8
我将使用Java Spring中的@Scheduled注解来定时执行任务,但如果任务速度较慢,则Spring默认情况下不会按照固定速率执行该任务。请问,是否有一些设置可以添加到我的Spring配置中以更改此行为? 示例:
@Service
public class MyTask{
    @Scheduled(fixedRate = 1000)
    public void doIt(){
        // this sometimes takes >1000ms, in which case the next execution is late
        ...
    }
}

我有一个解决方案,但看起来不太理想。基本上,我只是用线程池替换了默认的单线程执行器,然后我让一个计划方法调用异步方法,因为@Async注释允许并发执行:
@Service
public class MyTask{
    @Async
    public void doIt(){
        // this sometimes takes >1000ms, but the next execution is on time
        ...
    }
}

@Service
public class MyTaskScheduler{
    ...
    @Scheduled(fixedRate = 1000)
    public void doIt(){
        myTask.doIt();
    }
}

@Configuration
@EnableScheduling
@EnableAsync
public class MySpringJavaConfig{
    @Bean(destroyMethod = "shutdown")
    public Executor taskScheduler() {
        return Executors.newScheduledThreadPool(5);
    }
}

我的现实场景比较枯燥:在我的生产代码中,有一个任务,根据当前工作负载,需要花费10毫秒到10分钟不等的时间。理想情况下,我希望每1000毫秒从池中捕获一个新线程,以便随着工作负载增加并发线程数量也会增加。显然,我已经设置了线程数上限(包括其他控制)以避免事情失控。

2个回答

4
TaskScheduler API(支持Spring Scheduling行为的一部分)似乎是定义来防止您所请求的行为的。"subsequently" 和 "successive"似乎表明下次执行只会在当前执行完成后才会发生。此外,ScheduledExecutorService#scheduleAtFixedRate(...)(内置的 TaskScheduler 实现使用)也说:如果此任务的任何执行时间超过其周期,则后续执行可能会晚些开始,但不会同时执行。因此,还有另一层实现可以防止您想要的行为。一种可能的解决方案,我不建议使用,因为该API似乎没有围绕它进行构建,即定义并提供自己的TaskScheduler以并行运行任务。查看 @EnableScheduling SchedulingConfigurer以了解如何注册TaskScheduler

我感谢提供的参考资料,并正在研究SchedulingConfigurer和基于cron模式的作业。尽管如此,我不同意您对“subsequently”和“successive”的解释,并希望找到一个解决方案(即使有些笨拙),以实现我的目标。因此,我打算再等一段时间,以期望有人能够提出一个具体的功能性Spring配置,然后再接受这个答案。 - james turner

2

目前我发现的最佳解决方案是简单地使用委托使方法调用异步。这种方式的优点在于它允许我在执行工作的方法所在的同一类中声明计划:

@Service
public class AsyncRunner {
    @Async
    public void run(Runnable runnable) {
        runnable.run();
    }
}

@Service
public class MyTask{
    ...
    @Scheduled(fixedRate = 1000)
    public void scheduleIt(){
        asyncRunner.run(this::doIt);
    }
    public void doIt(){
        // this sometimes takes >1000ms, but the next execution is on time
        ...
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接