Java 21 introduced virtual threads as a stable feature.
Virtual threads are lightweight java.lang.Thread instances designed to support very high concurrency without assigning one operating-system thread to each Java thread for its entire lifetime. They are especially useful for thread-per-request servers that spend significant time waiting for network, database, or other blocking I/O. The runtime can suspend a waiting virtual thread and let its carrier platform thread run other work.
Virtual threads were developed through Project Loom. JEP 425 delivered them as a preview in Java 19, and JEP 436 offered a second preview in Java 20. JEP 444 finalized the feature in Java 21, which is why Java 19 and Java 20 are tempting but incorrect answers: they exposed the technology, but not as a permanent standard feature.
Virtual threads do not make CPU work faster and are not a replacement for every platform thread. They are intended for large numbers of mostly waiting tasks. Because they are cheap and typically short-lived, the Java documentation recommends creating one per task rather than placing virtual threads in traditional pools.