Skip to content

With virtual threads enabled, separate fixed-delay tasks cannot run concurrently #31900

@kzander91

Description

@kzander91

Framework: 6.1.2
Boot: 3.2.1

With spring.threads.virtual.enabled=true and otherwise default config, all methods annotated with @Scheduled(fixedDelay = ...) are executed on the same virtual thread, preventing multiple scheduled methods from running at the same time. cron and fixedRate tasks are not limited like this and run on separate threads (but of course allow executions of the same task to overlap).
The documentation states:

There is also a new option called SimpleAsyncTaskScheduler which is aligned with JDK 21’s Virtual Threads, using a single scheduler thread but firing up a new thread for every scheduled task execution.

This behaviour is most likely due to #31334, but shouldn't separate fixed-delay tasks still be allowed to run in parallel?
The following demonstrates this behaviour:

@Slf4j
@EnableScheduling
@SpringBootApplication
public class DemoApplication {

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

    @Scheduled(fixedDelay = 1000)
    public void sched1() throws InterruptedException {
        log.info("Starting sched1, sleeping for five seconds. Thread: {}", Thread.currentThread());
        TimeUnit.SECONDS.sleep(5L);
        log.info("Done with sched1.");
    }

    @Scheduled(fixedDelay = 1000)
    public void sched2() throws InterruptedException {
        log.info("Starting sched2, sleeping for five seconds. Thread: {}", Thread.currentThread());
        TimeUnit.SECONDS.sleep(5L);
        log.info("Done with sched2.");
    }

}

This produces output like this, showing that even while one task is blocked, the other one has to wait:

2023-12-23T22:34:08.092+01:00  INFO 23560 --- [   scheduling-1] com.example.demo.DemoApplication         : Starting sched1, sleeping for five seconds. Thread: VirtualThread[#50,scheduling-1]/runnable@ForkJoinPool-1-worker-4
2023-12-23T22:34:13.093+01:00  INFO 23560 --- [   scheduling-1] com.example.demo.DemoApplication         : Done with sched1.
2023-12-23T22:34:13.093+01:00  INFO 23560 --- [   scheduling-1] com.example.demo.DemoApplication         : Starting sched2, sleeping for five seconds. Thread: VirtualThread[#50,scheduling-1]/runnable@ForkJoinPool-1-worker-4
2023-12-23T22:34:18.094+01:00  INFO 23560 --- [   scheduling-1] com.example.demo.DemoApplication         : Done with sched2.

Is this behaviour intentional? If so, I would have expected a note about this in the docs...

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: documentationA documentation task

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions