Platform Threads and Virtual Threads.
Platform Threads
When we create a thread object in Java, it includes the code to be executed and the start method. Upon invoking the start method, the following steps occur:
OS Thread Creation: The OS creates and starts a new thread within our application process.
JVM Allocation: The JVM allocates a fixed-size stack space to store the thread's local variables.
From this point, the OS is responsible for scheduling and running the threads on the CPU, managing them just like any other threads.
In the JVM, a thread object is essentially a thin wrapper around an OS thread. These are known as platform threads.
Characteristics of Platform Threads
Heavyweight: Platform threads are expensive to create and manage.
Limited Resources: They map one-to-one to OS threads, which are limited resources.
Fixed Stack Space: Each platform thread requires a fixed stack space within the JVM.
Virtual Threads
Virtual Threads are introduced in JDK 21.
Unlike platform threads, virtual threads are fully managed by the JVM:
No Fixed Stack: They do not come with a fixed-sized stack(stack can grow and shrink dynamically as needed. This is managed by the JVM, allowing for more efficient memory usage).
JVM Management: The OS is not involved in their creation or management, and it is not even aware of their existence.
Java Objects: Virtual threads are like any other Java objects allocated on the heap and can be reclaimed by the JVM's garbage collection when no longer needed.
Advantages of Virtual Threads
Lightweight: Virtual threads are cheap and fast to create in large quantities.
Efficient Management: They offer efficient resource management compared to platform threads.
Execution of Virtual Threads
Virtual threads require a mechanism to run on the CPU. When at least one virtual thread is created, the JVM internally creates a small pool of platform threads.
Carrier Threads
Mounting: When the JVM wants to run a virtual thread (e.g., Virtual Thread A), it mounts it on one of the platform threads from the pool, known as a carrier thread.
Execution Completion: If the virtual thread finishes execution, the JVM unmounts it, making the carrier thread available for other virtual threads. The virtual thread object becomes garbage and can be cleaned up.
In-Progress Threads: If a virtual thread cannot make progress, the JVM unmounts it and saves its current state (instruction pointer and stack snapshot) on the heap. The carrier thread can then be used to mount another virtual thread.
Resuming Virtual Threads
When a previously unmounted virtual thread wants to continue:
Available Carrier Threads: If a carrier thread is available, the virtual thread is simply remounted.
No Available Carrier Threads: If no carrier threads are available, the virtual thread must wait.
Developer Control
Developers have minimal control over the carrier threads and the scheduling of virtual threads on them. The JVM handles this management under the hood.