High concurrency and multithreading have always been the difficulties in Java programming, and also the key points in the interview questions. Java developers have also been trying to use multithreading to solve the concurrency problem of application servers. But multithreading is not easy, and a new technology has emerged, virtual threading.

Traditional multithreading pain points

However, it is not easy to write multithreaded code. The execution order is difficult to control, the thread safety of shared variables, the observability of exceptions and so on are the difficulties of multithreaded programming.

If each request is processed in one thread for the duration of the request, the number of threads must grow with throughput in order to increase the throughput of the application. Unfortunately threads are a scarce resource, creating a thread is expensive, even the introduction of pooling techniques does not reduce the cost of creating new threads, and the CURRENT threading implementation of the JDK limits the throughput of applications to levels far below what the hardware can support.

For this reason, many developers have turned to asynchronous programming, such as CompletableFuture or the now-hot reactive framework. But these techniques are either bound by “callback hell” or lack visibility.

Addressing these pain points and improving the harmony of the Java platform makes it necessary to implement the thread-per-request style. Is it possible to implement a “low-cost” virtual thread that maps to the system thread to reduce direct operations on the system thread? The idea should be ok! So the Java community initiated the JEP 425 proposal on virtual threads.

Virtual thread

Virtual threads should be cheap and can be created without worrying about massive 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 transient and have a shallow call stack, performing only a single task HTTP client call or a single JDBC query. The equivalent of Platform Threads (now traditional JVM Threads) ** are heavy and expensive, and therefore must generally be pooled. They tend to be long-lived, have deep call stacks, and are shared across many tasks.

In summary, virtual threads retain a reliable threadper-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 your current multi-threading habits, using apis that are easier to use, compatible with older multi-threading designs, and not affecting the extensibility of your code at all.

The difference between platform and virtual threads

To better understand this design, the draft compares the two threads.

The current thread

Each java.lang.Thread is now a platform Thread that runs Java code on the underlying operating system Thread and captures the operating system Thread for the entire life of the code. The number of platform threads is limited by the number of OS threads.

Platform threads do not disappear by adding virtual threads.

Virtual threads of the future

Virtual threads are a lightweight implementation 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, in which a large number (M) of virtual threads are scheduled to run on a small number (N) of OS threads. The JDK’s virtual thread scheduler is a ForkJoinPool work-stealing mechanism that runs in FIFO mode.

We can create 10,000 virtual threads at will:

// Preview the code
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0.10 _000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  
Copy the code

Don’t have to worry about whether the hardware resources to live, in turn, if you use the Executors. NewCachedThreadPool thread () to create 10000 platform, on most operating systems are easy to collapse due to lack of resources.

Designed for throughput

But again, virtual threads are not designed to speed up execution. They are no faster than platform threads, and they exist to provide scale (higher throughput), not speed (lower latency). There may be many more of them than platform threads, and therefore, 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 (over several thousand).

  • The workload is cpu-independent, because having many more threads than the processor kernel does not improve throughput in this case.

Virtual threads help to 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 is not the whole story. 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, analyzing, and monitoring threads. Being in virtual threads also increases code visibility, allowing developers to better debug code.

New Threading API

A new thread API design has been added for this purpose, which is currently released as follows:

  • Thread.Builder A Thread Builder.

  • ThreadFactory can batch build thread factories with the same characteristics.

  • Thread.ofvirtual () creates a virtual Thread.

  • Thread.ofplatform () creates a platform Thread.

  • Thread. StartVirtualThread (Runnable) a a convenient way of creating virtual Thread then start.

  • Thread.isvirtual () tests whether a Thread isVirtual.

There are a lot of not a demo, interested in their own to see JEP425.

conclusion

There are many more details to JEP425, but that’s all I can read based on my lack of understanding. Coroutines have been around for a long time in the Java community, and it’s good news that they’re finally taking real action. There are a lot of things involved, though, including platform thread compatibility, some impact on ThreadLocal, and some impact on JUC. It may take several previews before it hits the ground. Fat brother may not be able to catch up with that time, but many younger students should be able to.

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn