High concurrency and multithreading have always been difficult points in Java programming, and they are also the main points of interview questions. Java developers have also been trying to use multithreading to solve application server concurrency problems. But multi-threading is not easy, so a new technology has appeared, which is virtual thread.
Pain points of traditional multithreading
But it is not easy to write multi-threaded code. The execution sequence that is difficult to control, the thread safety of shared variables, the observability of exceptions, etc. are all difficulties in multi-threaded programming.
If each request is processed in a thread for the duration of the request, then to increase the throughput of the application, the number of threads must grow with the throughput. Unfortunately threads are a scarce resource, creating a thread is expensive, even the introduction of pooling cannot reduce the cost of creating new threads, and the JDK's current threading implementation limits application throughput to well below hardware level that can be supported.
For this reason, many developers turn to asynchronous programming, such as CompletableFuture
or reactive frameworks that are hot now. But these techniques either cannot escape "callback hell" or lack observability.
To solve these pain points and enhance the harmony of the Java platform, it has become necessary to implement a thread-per-request style for each request. Is it possible to implement a "low cost" virtual thread to map to the system thread to reduce the direct operation of the system thread? Ideas should be fine! So the Java community launched the JEP 425 proposal on virtual threads.
virtual thread
Virtual threads ( virtual threads ) should be very cheap and can be created without worrying about system hardware resources, and should not be pooled. A new virtual thread should be created for each application task. Therefore, most virtual threads will be short-lived and have shallow call stacks, performing only a single task HTTP client call or a single JDBC query. The corresponding platform threads (Platform Threads, which are now traditional JVM threads) are heavyweight and expensive, so they usually have to be pooled. They tend to be long lived, have deep call stacks, and are shared among many tasks.
In summary, virtual threads preserve a reliable independent thread-per-request style that is compatible with the design of the Java platform, while optimizing hardware utilization. Using virtual threads does not require learning new concepts, or even changing the habit of operating multi-threading, using a more accessible API , compatible with previous multi-threading designs, and does not affect the scalability of the code at all.
The difference between platform threads and virtual threads
To better understand this one design, the draft compares the two threads.
current thread
Now each java.lang.Thread
is a platform thread that runs Java code on the underlying OS thread and captures the OS thread for the entire lifetime of the code. The number of platform threads is limited by the number of OS threads.
Platform threads do not exit the stage of history by joining virtual threads.
future virtual threads
Virtual threads are lightweight implementations of threads provided by the JDK rather than the operating system. They are a form of user-mode threads that have been successful in other multithreaded languages (such as coroutines in Golang and processes in Erlang). Virtual threads employ M:N scheduling, where a large number (M) of virtual threads are scheduled to run on a smaller number (N) of OS threads. The JDK's virtual thread scheduler is a ForkJoinPool
work-stealing mechanism that operates in FIFO mode.
We can freely create 10,000 virtual threads:
// 预览代码
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
Don't worry about whether the hardware resources can handle it, conversely, if you use Executors.newCachedThreadPool()
to create 10,000 platform threads, it is easy to crash due to insufficient resources on most operating systems.
Designed for throughput
But here is still a point to note, virtual threads are not designed to improve execution speed . It's not faster than platform threads, they exist to provide scale (higher throughput), not speed (lower latency). They can be much more numerous than platform threads, so according to Little's law, they can achieve the higher concurrency required for higher throughput.
In other words, virtual threads can significantly improve application throughput
- the number of concurrent tasks is high (more than a few thousand), and
- The workload is not CPU bound, as having much more threads than processor cores does not improve throughput in this case.
Virtual threads help improve the throughput of traditional server applications precisely because such applications contain a large number of concurrent tasks that spend a lot of time waiting.
Enhanced observability
Writing clean code isn't everything. A clear representation of the state of a running program is also important for troubleshooting, maintenance, and optimization, and the JDK has long provided mechanisms for debugging, profiling, and monitoring threads. Code observability is also enhanced in virtual threads, allowing developers to better debug code.
New threading API
To this end, a new thread API design has been added. The currently released parts are as follows:
-
Thread.Builder
Thread Builder. -
ThreadFactory
can build thread factories with the same characteristics in batches. -
Thread.ofVirtual()
Create a virtual thread. -
Thread.ofPlatform()
Create a platform thread. -
Thread.startVirtualThread(Runnable)
A convenient way to create and then start a virtual thread. -
Thread.isVirtual()
Test whether the thread is a virtual thread.
There are many more that will not be demonstrated one by one. If you are interested, you can see JEP425 by yourself.
Summarize
There are still many details in JEP425 . Based on my lack of personal understanding, I can only interpret so much. Coroutines have been called out in the Java community for a long time, and now there is finally real action, which is exciting news. However, there are still many things involved in this function, including the compatibility of platform threads, some effects on ThreadLocal
, and effects on JUC. It may take multiple previews to finally land. Fat brother may not be able to catch up with that time, but many young classmates should be able to catch up.
关注公众号:Felordcn 获取更多资讯
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。