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

jam*_*ner 7 java spring multithreading

我正在尝试使用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
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个解决方案,但似乎不太理想.基本上,我只是用线程池替换默认的单线程执行器,然后我有一个调度方法调用异步方法,因为@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的真实场景的无聊细节:在我的生产代码中,我的任务需要10毫秒到10分钟,具体取决于当前的工作负载.理想情况下,我想每隔1000毫秒从池中捕获一个新线程,以便并发线程数随工作负载而增加.显然我有一个上限(在其他控件之中),以防止事情失控.

Sot*_*lis 4

API TaskScheduler(支持一些 Spring 调度行为)似乎是为了防止您请求的行为而定义的

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

参数

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

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

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

如果该任务的任何执行时间超过其周期,则后续执行可能会延迟开始,但不会并发执行

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

一种可能的解决方案是定义并提供您自己的TaskScheduler并发运行任务的解决方案,因为 API 似乎不是围绕它构建的,所以我不推荐这种解决方案。查看@EnableSchedulingSchedulingConfigurer了解如何注册TaskScheduler.