如标题所示,我试图使用Scheduled批注的fixedRate参数,以便每秒调用一个函数。这是我正在使用的代码:

  //execute once every second
  @Scheduled(fixedRate = 1000)
  private void pullLiveDataFromExternalServer() throws InterruptedException {

    System.err.println("START THREAD " + Thread.currentThread().getId());
    Thread.sleep(5500L);
    System.err.println("END THREAD " + Thread.currentThread().getId());

  }

以我的理解,该功能应该在打印第一个“END THREAD”之前打印“START THREAD”五次。

问题在于该函数首先打印“START THREAD”,然后等待5.5秒,打印“END THREAD”,然后进入“START THREAD”,依此类推...看来调度程序在等待之前的执行完成之前,它开始新的执行,但是fixedRate属性不是这种情况。

我仔细阅读了一下,发现@Scheduled注释的默认调度程序只有一个线程,因此我创建了一个配置以将池大小更改为8。
@Component
public class SchedulingConfigurerConfiguration implements SchedulingConfigurer {
  @Override
  public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(8);
    taskScheduler.initialize();
    taskRegistrar.setTaskScheduler(taskScheduler);
  }
}

但是fixedRate属性的行为没有改变,并且调度程序在开始新的执行之前仍在等待上一次执行的结束。为什么会这样呢?

我正在使用的Spring Boot版本是v1.5.8.RELEASE。

最佳答案



这是正确的,这是预期的行为。无论fixedRate还是fixedDelay,每个计划的任务都不会并行运行。即使调用花费的时间超过配置的fixedRate,也是如此。

最终,固定速率调度将导致对ScheduledExecutorService.scheduleAtFixedRate的调用。它的javadoc声明以下内容:



如果同一计划任务的多个调用有可能并行运行,那么问题中的示例将耗尽所有可用线程。每1000毫秒将使用一个新线程,而每5500毫秒将仅重新提供一个线程。

09-04 04:46