Short Answer:
Green Threads had an N:1 mapping with OS Threads. All the Green Threads ran on a single OS Thread. With Virtual Threads, multiple virtual threads can run on multiple native threads (n:m mapping)
A bit more details from the JEP 425
Java's green threads all shared one OS thread (M:1 scheduling) and were eventually outperformed by platform threads (Java's Native Threads) implemented as wrappers for OS threads (1:1 scheduling)
Virtual threads employ M:N scheduling, where a large number (M) of virtual threads is scheduled to run on a smaller number (N) of OS threads.
Just a small overview
Thread Type |
Description |
Java Thread Type (M) : Native Threads(N) |
Platform Threads |
A wrapper for OS Threads. |
1:1 |
Green Threads |
Runs multiple "Green Threads" on a single OS Thread. |
M:1 |
Virtual Threads |
Runs multiple Virtual Threads on Multiple OS threads |
M:N (M > N) |
Full Quote from JEP
Virtual threads are a lightweight implementation of threads that is
provided by the JDK rather than the OS. They are a form of user-mode
threads, which have been successful in other multithreaded languages
(e.g., goroutines in Go and processes in Erlang). User-mode threads
even featured as so-called "green threads" in early versions of Java,
when OS threads were not yet mature and widespread. However, Java's
green threads all shared one OS thread (M:1 scheduling) and were
eventually outperformed by platform threads, implemented as wrappers
for OS threads (1:1 scheduling). Virtual threads employ M:N
scheduling, where a large number (M) of virtual threads is scheduled
to run on a smaller number (N) of OS threads.