44
@Scheduled(fixedDelay = 5000)
public void myJob() {
     Thread.sleep(12000);
}

如果之前的例程尚未完成,如何防止此春季作业运行?

4

2 回答 2

91

默认情况下,spring 使用单线程 Executor。所以没有两个@Scheduled 任务会重叠。即使是完全不相关的类中的两个@Scheduled 方法也不会重叠,因为只有一个线程来执行所有@Scheduled 任务。

此外,即使您将默认的 Executor 替换为基于线程池的 Executor,这些 Executor 通常也会延迟任务实例的执行,直到之前调度的实例完成。这适用于基于 fixedDelay、fixedInterval 和 cron的计划。例如,这个 spring 配置将创建一个使用线程池的ScheduledThreadPoolExecutor,但不允许您希望的相同调度的并发实例:

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

这是ScheduledThreadPoolExecutor::scheduleAtFixedRate 的 javadoc,它指定:

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

注意:此功能不适用于@Async 任务。spring 将根据需要创建尽可能多的并发实例(如果池中有足够的线程)。

于 2015-05-19T13:42:21.047 回答
46

使用fixedDelay,期间是在工作完成后测量的,所以不用担心。

于 2014-06-04T09:12:28.007 回答