如何防止Spring中重叠的时间表?

mem*_*und 34 java spring spring-scheduled

@Scheduled(fixedDelay = 5000)
public void myJob() {
     Thread.sleep(12000);
}
Run Code Online (Sandbox Code Playgroud)

如果上一个例程尚未完成,如何防止此弹簧作业运行?

jam*_*ner 70

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

此外,即使您使用基于线程池的执行程序替换默认的Executor,这些执行程序通常也会延迟执行任务实例,直到先前计划的实例完成为止.对于fixedDelay,fixedInterval和基于cron的计划,这是正确的.例如,这个spring配置将创建一个使用线程池的ScheduledThreadPoolExecutor,但不允许同一个日程表的并发实例:

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

这是ScheduledThreadPoolExecutor :: scheduleAtFixedRatejavadoc,它指定:

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

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

  • @EricMajerus我对此表示怀疑。spring几乎可以肯定不会为每个执行创建单独的对象或指针。很有可能它只是保持一个指向“下一个”开始时间的指针。因此,即使“堆积”了一百万个工作,也不应该有任何资源泄漏。 (2认同)
  • 对于fixedDelay,fixedInterval和基于* cron *的计划,这是正确的!请加粗这行,这是现实生活中的救星!! (2认同)

Jos*_*tin 33

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

  • 这是一个有趣的声明!如果我以后想切换到`cron`(确实是打算的)怎么办? (2认同)
  • 使用单线程执行器,如果您不设置池大小或根本不声明调度程序,则这是默认设置。 (2认同)