Virtual Threads in Java


  • What are virtual threads?
    Lightweight threads introduced in Java 19/21, managed by the JVM.
  • Why are they useful?
    They allow running millions of concurrent tasks efficiently, especially for I/O-heavy applications.
  • How are they different from platform (OS) threads?
    Virtual threads are cheaper to block and resume, making blocking I/O operations inexpensive.
  • How do they help developers?
    They simplify concurrent programming—no need for complex callbacks or reactive code.
  • How to create them?
    Use:
    • Executors.newVirtualThreadPerTaskExecutor()
    • Thread.startVirtualThread()
  • Best use case:
    Ideal for I/O-bound workloads with many concurrent tasks.
  • Not suitable for:
    CPU-intensive tasks—use platform threads instead.
  • Thread limits:
    Don’t limit thread count. Instead, use resource controls like semaphores to avoid overloading systems.
  • Avoid “pinning”:
    Some operations (like synchronized blocks) can force virtual threads to stick to one carrier thread, reducing concurrency.
  • Performance tip:
    A single JVM with virtual threads often performs better than multiple JVMs for I/O-heavy workloads.
  • JVM lifecycle note:
    Virtual threads are daemon threads, so make sure the JVM stays alive when needed.
  • Overall benefit:
    Combines massive concurrency with simple, readable code, improving scalability and developer productivity.

Virtual Threads v/s Platform (Normal) Threads

AspectVirtual ThreadsPlatform Threads
Thread TypeLightweight, managed by JVM, multiplexed on few OS threadsHeavyweight, directly mapped to OS threads
Creation CostVery low; can create millionsHigh; limited by OS and memory
Blocking BehaviorCheap; JVM suspends and reuses carrier threadsExpensive; blocks OS thread
Best Use CaseI/O-bound, high concurrency tasksCPU-bound or low concurrency tasks
PerformanceScales well with many blocking tasksBetter for CPU-intensive workloads
Stack StorageStored on heap; shallow stacksStored on OS thread stack; deeper stacks
SchedulingJVM schedules on carrier threadsOS handles scheduling
Short-circuiting & StateSupports complex stateful operationsLimited to basic thread behavior
Daemon Thread SupportAlways daemon; doesn’t keep JVM aliveCan be daemon or user thread

Single JVM Process with Virtual Threads v/s Multiple JVM Processes with Virtual Threads

AspectSingle JVM with Virtual ThreadsMultiple JVMs with Virtual Threads
Resource SharingShares memory (heap), garbage collector, and thread scheduler—more efficientEach JVM has its own memory and GC—more isolated but duplicates resources
I/O ConcurrencyScales better and handles many I/O tasks efficientlyMore overhead, less efficient for high I/O concurrency
CPU-bound TasksMay face issues like GC pauses and thread contentionBetter isolation for CPU-heavy tasks, reducing interference
Management ComplexityEasier to deploy, monitor, and manageHarder to manage due to multiple JVMs running separately
Fault IsolationOne JVM crash affects all tasksCrashes are isolated to individual JVMs
I/O PerformanceGenerally faster due to shared scheduling and lightweight threadsSlower due to overhead from multiple JVMs