Spring Scheduled fixedRate not working properly

孤人 提交于 2021-02-07 20:30:38

问题


As the title says, I am trying to use the fixedRate paramater of the Scheduled annotation in order to invoke a function every second. Here is the code that I am using:

  //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());

  }

The way I understand it, the function should print "START THREAD" five times before the first "END THREAD" is printed.

The problem is that the function first prints "START THREAD" and then waits 5.5 seconds, prints "END THREAD", and then goes "START THREAD" and so on... It looks like the scheduler waits for the previous execution to finish before it starts the new execution but that should not be the case for the fixedRate attribute.

I read into it a bit more and found out that the default scheduler for @Scheduled annotation has only one thread, so I created a configuration to change the pool size to 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);
  }
}

But the behaviour of the fixedRate attribute was no changed and the scheduler was still waiting for the end of the previous execution before starting a new one. Why is this happening ?

The spring boot version that I am using is v1.5.8.RELEASE.


回答1:


It looks like the scheduler waits for the previous execution to finish before it starts the new execution

This is correct and it is the intended behaviour. Each scheduled task, irrespective of fixedRate or fixedDelay, will never run in parallel. This is true even if the invocation takes longer than the configured fixedRate.

Ultimately, fixed rate scheduling results in a call to ScheduledExecutorService.scheduleAtFixedRate. Its javadoc states the following:

If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.

If it was possible for multiple invocations of the same scheduled task to run in parallel, the example in your question would exhaust all of the available threads. A new thread would be used every 1000ms and a thread would only become available again every 5500ms.




回答2:


The simplest working example with Spring Boot. Configure your application:

@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);
    }

}

Add @Async to your scheduled task:

@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());
    }
}


来源:https://stackoverflow.com/questions/49671257/spring-scheduled-fixedrate-not-working-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!