Virtual Threads : Java 21

Java 21 came with an exciting feature of Virtual Thread - Lightweight Threads. The idea is to achieve optimal hardware utilisation, which has been a bottleneck for the conventional java.lang.Thread - platform threads.

Platform threads are 1:1 mapped with OS Thread, which makes them powerful to accomplish all possible tasks. java.lang.Thread is a thin layer on actual OS threads, which are quite heavy. The number of thread application can support depends on the hardware capacity of the system.

Let’s say thread memory consumption is 1 MB, to support 1 million threads in concurrent application at the time of heavy load, you will need 1 TB of memory. One thread per request style of implementation also suffer due to this limitation - asynchronous programming can solve this upto some extent but it has its own drawbacks.

Virtual threads effectively shares the platform thread. Rather than holding the platform thread for entire lifetime, it runs short lived tasks and for the needed executions - not while it waits for I/O. This allows insane number of concurrent operations without need of additional threads or hardware capacity. This brings up the new way to deal with concurrency in Java applications.

Virtual threads can be created with java.lang.Thread builder approach,

Runnable function = () -> System.out.println("Something to execute in Virtual Thread!");
Thread virtual = Thread.startVirtualThread(function);

In addition to that, java.util.concurrent.ExecutorService also has factory method for Virtual threads,

ExecutorService virtualExecutor = Executors.newVirtualThreadPerTaskExecutor();

Virtual threads are daemon threads, join() to wait on the main thread. Thread local variables of virtual thread are not accessible to carrier thread or vice versa.