问题
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