Scheduled virtual thread per task executor

Daniel Schmid daniel at
Tue Oct 10 08:56:27 UTC 2023

I came across a discussion on how to get a ScheduledExecutorService 
implementation that uses a virtual thread for each task without needing 
to pool the virtual threads.

For most cases, it would be possible to just not use a 
ScheduledExecutorService and just sleep in the virtual threads like this:

Thread.ofVirtual().start(() -> {
     try {
         Thread.sleep(Duration.ofMinutes(1));//initial delay
     } catch (InterruptedException e) {
     while (!Thread.currentThread().isInterrupted()) {
         try {
             Thread.sleep(Duration.ofMinutes(1));//delay between tasks
         } catch (InterruptedException e) {

However, the API of ScheduledExecutorService is convenient for many 
cases (shutdown, automatic scheduling without needing to deal with 
interruption manually, etc.).
It would be useful (also for migrating existing systems) to be able to 
use the API of ScheduledExecutorService in a way that virtual threads 
are used for handling, either by a virtual thread being created that 
waits for the delay to elapse (for each scheduled task) or by just 
creating the virtual thread when the task should be executed.
The latter could be done by just creating a normal 
ScheduledThreadPoolExecutor with a core pool size of 0 (to prevent any 
pooling) and a virtual thread factory. Would that still attempt to pool 
virtual threads in some way?
However, I think the more intuitive way of having a "virtual thread 
ScheduledExecutorService" would be for virtual threads to be created on 
schedule() and just sleep.

It would also be possible to create a custom implementation using 
AbstractExecutorService, Executors.newVirtualThreadPerTaskExecutor() (as 
a delegate) and a custom FutureTask implementing ScheduledFuture but 
this would require certain effort and understanding of 
AbstractExecutorService/FutureTask/etc. on the implementation/user side 
and seems easy to get wrong (especially with shutdown/cancellation).

Is there a specific reasoning behind the JDK not providing a 
ScheduledExecutorService variant of 
Executors.newVirtualThreadPerTaskExecutor()? Are there any plans to 
implement this in the future?

Also, which of these approaches (reimplementing ScheduledExecutorService 
code using manual sleep()s, a ScheduledThreadPoolExecutor with a core 
pool size of 0 and virtual threads or a custom implementation) should be 
preferred in application?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4490 bytes
Desc: Kryptografische S/MIME-Signatur
URL: <>

More information about the loom-dev mailing list