How to specify scheduler for virtual threads

Alan Bateman Alan.Bateman at
Wed Nov 20 10:11:31 UTC 2019

On 20/11/2019 00:21, Arkadiusz Gasiński wrote:
> Awesome, thanks!
> I've played with it for a moment and managed to come up with this 
> weird code below:
> var dinosaurs = Executors.newFixedThreadPool(2); var factory = Thread.builder()
>      .virtual()
>      .scheduler(dinosaurs)
>      .name("virtual-thread-", 1)
>      .inheritThreadLocals()
>      .factory(); var virtualOverDinosaurs = Executors.newFixedThreadPool(1000, factory);
> If I understand my code correctly, I created an Executor that 
> multiplexes 1000 virtual threads over 2 dinosaur threads.
This looks like a thread pool that reuses 1000 virtual threads that are 
multiplexed over 2 kernel/dinosaur threads.

> What I'm confused about is that once I started submitting tasks to 
> this virtualOverDinosaurs executor, it quickly became apparent that it 
> does not create a new virtual thread for each task submitted, but 
> rather multiplexes these tasks over some rather small number of 
> virtual threads.
If these tasks are doing blocking operations then I assume you will 
eventually see that all 1000 virtual threads are being used.

> My questions then are:
> Does it mean that this virtualOverDinosaurs executor caches virtual 
> threads? If so what does it mean to cache virtual thread?
> Should something like this be even possible? I thought that one of the 
> purposes of virtual threads was to support 1:1 mapping between a task 
> and a thread and this is apparently not the case here.
Virtual threads are cheap to create so there shouldn't be any need to 
create thread pools that re-use the same (virtual) thread to execute 
many tasks. If we find that people are caching/re-using virtual threads 
then we've got something wrong. So yes, expect a 1:1 relationship 
between virtual thread and task.

It is still early days but it might be that alternative ExecutorService 
implementations suited to virtual threads should be added. By this I 
mean that the submit/execute creates a new thread per task rather than 
re-using threads. There might be need to limit the concurrency to a 
maximum number of network or database connections for example. There are 
several things to explore to build up a more complete story.


More information about the loom-dev mailing list