Java / Java Concurrency and Multi Threading in Java 17 and Java 21 Interview questions
Explain the lifecycle of a virtual thread in Java 21?
A virtual thread's lifecycle looks like an ordinary thread's from the outside, it goes through NEW, RUNNABLE, and TERMINATED, plus WAITING/TIMED_WAITING/BLOCKED as needed, but the mechanics underneath are different.
flowchart LR
A[Created via Thread.ofVirtual] --> B[Scheduled onto a carrier platform thread]
B --> C{Blocking operation?}
C -- Yes, e.g. I/O --> D[Unmounted from carrier; carrier freed for other virtual threads]
D --> E[Operation completes]
E --> B
C -- No --> F[Runs to completion or yields]
F --> G[Terminated]
When created and started, a virtual thread is handed to the JVM's built-in scheduler, which is itself a ForkJoinPool, and mounted onto an available carrier (an ordinary platform thread). While it's doing CPU work or calling most JDK-supported blocking operations, it stays mounted.
When it hits a blocking point the JVM knows how to handle non-blockingly underneath, such as socket I/O, Thread.sleep(), or blocking on a java.util.concurrent lock, the JVM unmounts it, storing its stack in the heap and freeing the carrier thread to run a different virtual thread. Once the operation completes, the virtual thread is remounted on some available carrier, not necessarily the same one, and continues.
This mount/unmount cycle, invisible to application code, is what lets a small pool of carrier threads support enormous numbers of concurrently blocked virtual threads. When the virtual thread's task returns, it terminates and its resources are reclaimed like any object; there is no OS thread teardown cost since none was created.
More Related questions...