如何配置spring来执行重叠的fixedRate任务?

我正在尝试使用java spring中的@Scheduled注释以固定速率执行任务。 但是,默认情况下,如果任务比速率慢,spring将不会以固定速率执行fixedRate任务。 是否有一些设置我可以添加到我的弹簧配置来改变这种行为?

例子

@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毫秒从池中捕获一个新线程,以便并发线程数随工作负载而增加。 显然我有一个上限(在其他控件之中),以防止事情失控。

TaskScheduler API(支持一些Spring Scheduling行为)似乎被定义为阻止您请求的行为

计划给定的Runnable ,在指定的执行时间调用它,然后在给定的时间段内调用它。

参数

  • period连续执行任务之间的间隔(以毫秒为单位)

随后连续似乎表明下一次执行只会在当前执行完成后发生。

更重要的是, ScheduledExecutorService#scheduleAtFixedRate(..) (内置的TaskScheduler实现使用)也说

如果此任务的执行时间超过其周期,则后续执行可能会延迟, 但不会同时执行

因此,实现的另一层可以阻止您想要的行为。

一个可能的解决方案,我不建议使用,因为API似乎不是围绕它构建的,是定义并提供自己的TaskScheduler ,它同时运行任务。 查看@EnableSchedulingSchedulingConfigurer ,了解如何注册TaskScheduler

到目前为止,我发现的最佳解决方案是简单地使用委托来使方法调用异步。 这只是首选,因为它允许我在与执行工作的方法相同的类中声明调度:

 @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 ... } }