Continuations: The magic behind virtual threads in Java by Balkrishna Rawool

Learn how Java virtual threads achieve massive scalability through continuations - the mechanism for pausing & resuming lightweight threads with minimal resource usage.

Key takeaways
  • Virtual threads are lightweight user threads introduced in Java 21 that provide high scalability by requiring significantly less memory than platform threads

  • Continuations are the underlying mechanism enabling virtual thread functionality - they represent the current state of a program and allow pausing/resuming execution

  • Virtual threads use a many-to-many relationship with platform threads (carrier threads) - multiple virtual threads can share a small pool of platform threads

  • When a virtual thread is blocked (e.g. waiting for I/O), it gets unmounted from the platform thread, allowing other virtual threads to use that platform thread efficiently

  • Virtual threads should not be pooled since they are cheap to create and destroy, unlike platform threads which are expensive OS resources

  • The mounting/unmounting behavior of virtual threads is what enables their high scalability - platform threads aren’t wasted while virtual threads are blocked

  • Virtual threads require a platform thread to execute but can be unmounted when waiting, making them ideal for I/O-bound applications

  • Continuations work by manipulating the call stack - saving stack frames to heap memory when yielding and restoring them when resuming

  • You can create thousands or millions of virtual threads since they have low memory overhead compared to platform threads

  • The default number of carrier (platform) threads is set to match CPU cores, but can be configured via JVM arguments