Spring Scheduled fixedRate无法正常工作

时间:2018-04-05 11:29:19

标签: java multithreading spring-boot scheduled-tasks

正如标题所说,我正在尝试使用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属性的行为没有改变,并且调度程序在开始新的执行之前仍在等待上一次执行的结束。为什么会这样?

我使用的春季启动版本是v1.5.8.RELEASE。

2 个答案:

答案 0 :(得分:2)

  

看起来调度程序在开始新执行之前等待上一次执行完成

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

最终,固定费率调度会调用ScheduledExecutorService.scheduleAtFixedRate。它的javadoc说明如下:

  

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

如果同一个计划任务的多次调用可以并行运行,那么您问题中的示例将耗尽所有可用线程。每隔1000毫秒就会使用一个新线程,并且每隔5500毫秒就会再次使用一个线程。

答案 1 :(得分:1)

Spring Boot最简单的工作示例。配置您的应用程序:

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class SpringConfiguration implements AsyncConfigurer {

    public static void main(String[] args) {
        SpringApplication.run(SpringConfiguration.class);
    }

    @Override
    public Executor getAsyncExecutor() {
        return Executors.newScheduledThreadPool(8);
    }

}

@Async添加到您的计划任务中:

@Component
public class Task {

    //execute once every second
    @Scheduled(fixedRate = 1000)
    @Async
    public void pullLiveDataFromExternalServer() throws InterruptedException {
        System.err.println("START THREAD " + Thread.currentThread().getId());
        Thread.sleep(5500L);
        System.err.println("END THREAD " + Thread.currentThread().getId());
    }
}