The OpenJDK constantly works on improving the Java language. The new JEP 428: Structured Concurrency, which is now an incubating API, is aimed at simplifying multithreaded programming.
Concurrent execution of subtasks belonging to one task helps to reduce latency and speed up the operation process. In Java,
java.util.concurrent.ExecutorService is commonly used for concurrency operations. But the
ExecutorService doesn’t understand the task-subtask relationship, which means that
- If a subtask throws an exception, other subtasks may not notice that and continue working, leading to thread leaks
- If a task fails, subtasks continue running. It will also lead to thread leaks
- A task may not notice that a subtask has thrown an exception and will wait for other subtasks to execute instead of canceling them
It is possible to structure the code manually by introducing
try-with-resources, but writing such code is time-consuming. Therefore, there is a need for reliable and automatic concurrency structuring.
JEP 428 introduces a library for structured concurrency that treats multiple tasks from different threads as one unit. The task is split into subtasks, which return to the same code block nested in the block of a parent task. The parent task monitors the subtasks and waits for their result. This way, a tree-shaped hierarchy of tasks is built at runtime, with sibling subtasks being owned by a parent task. Such a hierarchy can be reified just like a call stack.
Structured concurrency allows to define clear entry and exit points of operations coming through the code block and brings the following benefits to the developers:
- It enables reliable coordination of virtual threads. Virtual threads are lightweight and can be used simultaneously in large numbers. Structured concurrency enables the processing of millions of virtual threads by dedicating threads to tasks and their subtasks.
- It enhances the reliability of multithreading by enforcing the delimitation and lifetime of operations: the lifetime of all concurrent sibling subtasks is confined within one syntactic block. Each subtask returns to its parent, and no subtask can finish after the task. If the parent notices the exception thrown by one subtask, it can cancel all other subtasks.
- Structured behavior of subtasks reporting only to their parent helps to prevent thread leaks and cancellation delays.
We are looking forward to this change as it may prove significant in the case of multithreaded server applications. If JEP 428 is introduced in JDK 19 as a preview, developers can test structured concurrency with virtual threads. As for now, you can read more about this feature on the OpenJDK website.