ExecutorService.awaitTermination and virtual threads

Ron Pressler ron.pressler at oracle.com
Mon Dec 9 18:15:02 UTC 2019


I don’t see you setting your Executor as the scheduler for the virtual threads,
but even if you did, you are correct that awaiting the termination of a virtual-thread 
scheduler is not the same thing as awaiting the termination of all virtual threads
scheduled by that scheduler. Setting the virtual thread scheduler is an advanced
mechanism to control the internal implementation details of virtual threads, not to mange
them on a high level. We will introduce mechanisms for managing threads.

- Ron


On 9 December 2019 at 17:30:22, Arkadiusz Gasiński (jigga at jigga.pl) wrote:

Hi,  

I know loom's still in the prototyping phase but just wanted to share one  
observation related to supplying custom scheduler/executor to virtual  
thread factory.  

The first example shows how I'm used to working with ExecutorService with  
old Threads. The code is in Kotlin, but I hope that this does not distract  
you from the point I'm trying to make (plus shows that Kotlin works with  
the latest loom build).  

fun main() {  
val task = Runnable {  
println("${Thread.currentThread().name} - Going to sleep for  
10 seconds")  
TimeUnit.SECONDS.sleep(10)  
println("${Thread.currentThread().name} - Woke up after 10 seconds")  
}  

val threadScheduler = Executors.newCachedThreadPool()  

threadScheduler.submit(task)  
threadScheduler.submit(task)  
threadScheduler.submit(task)  

TimeUnit.SECONDS.sleep(1)  
threadScheduler.shutdown()  
threadScheduler.awaitTermination(15, TimeUnit.SECONDS)  
}  


The case here is that the *awaitTermination* method at the end of the main  
waits until all submitted tasks complete, which is what I'm actually used  
to.  

Now, when I switch to virtual threads...  

fun main() {  
val task = Runnable {  
println("${Thread.currentThread().name} - Going to sleep for  
10 seconds")  
TimeUnit.SECONDS.sleep(10)  
println("${Thread.currentThread().name} - Woke up after 10 seconds")  
}  

val scheduler = Executors.newSingleThreadExecutor()  
val virtualThreadFactory =  
Thread.builder().virtual().daemon(false).name("virtual-thread-",  
1).factory()  

virtualThreadFactory.newThread(task).start()  
virtualThreadFactory.newThread(task).start()  
virtualThreadFactory.newThread(task).start()  

TimeUnit.SECONDS.sleep(1)  
scheduler.shutdown()  
scheduler.awaitTermination(10, TimeUnit.SECONDS)  
}  


The issue here is that now the awaitTermination method does not wait for  
all running virtual threads to finish. Correct me if I'm wrong, but I  
assume that this is due to the fact that this executor service is simply  
not aware of the running virtual threads (although the executor service  
serves as virtual thread scheduler, so maybe it's actually aware, in which  
case I have no clue why it behaves like this)?  

Thanks,  
Arek  


More information about the loom-dev mailing list