JEP 428:简化 Java 多线程编程的结构化并发

JEP 428,结构化并发(孵化器),已从JDK 19 的 Proposed 到 Target 提升到 Targeted 状态。在 Project Loom 的保护下,这个JEP 提议 通过引入一个库来简化多线程编程,以将在不同线程上运行的多个任务视为原子操作。因此,它将简化错误处理和取消,提高可靠性并增强可观察性。这仍然是一个孵化的 API。

这允许开发人员使用StructuredTaskScope该类来组织他们的并发代码。它将一系列子任务视为一个单元。子任务将在它们自己的线程上通过单独分叉创建,然后作为一个单元加入,并可能作为一个单元取消;它们的异常或成功结果将由父任务聚合和处理。让我们看一个例子:

Response handle() throws ExecutionException, InterruptedException {
   try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
       Future<String> user = scope.fork(() -> findUser());
       Future<Integer> order = scope.fork(() -> fetchOrder());

       scope.join(); // Join both forks scope.throwIfFailed(); // ... and propagate errors // Here, both forks have succeeded, so compose their results return new Response(user.resultNow(), order.resultNow());
   }
}

上述handle()方法表示服务器应用程序中的任务。它通过创建两个子任务来处理传入请求。比如ExecutorService.submit(),StructuredTaskScope.fork()接受 aCallable并返回 a Future。与 不同ExecutorService的是,返回Future的不是通过 加入的Future.get()。此 API 在 JEP 425虚拟线程(预览版)之上运行,同样针对 JDK 19。

上面的示例使用StructuredTaskScopeAPI,因此要在 JDK 19 上运行它们,开发人员必须添加模块,并启用预览功能以使用虚拟线程: jdk.incubator.concurrent

编译上述代码,如以下命令所示:

javac --release 19 --enable-preview --add-modules jdk.incubator.concurrent Main.java

运行程序也需要相同的标志:

java --enable-preview --add-modules jdk.incubator.concurrent Main;

但是,可以使用源代码启动器直接运行它。在这种情况下,命令行将是:

java --source 19 --enable-preview --add-modules jdk.incubator.concurrent Main.java

jshell选项也可用,但也需要启用预览功能:

jshell --enable-preview --add-modules jdk.incubator.concurrent

结构化并发带来的好处是多方面的。它在调用者方法和它的子任务之间创建了一个父子关系。例如,在上面的示例中,handle()任务是父任务,其子任务和是子任务。结果,整个代码块变得原子化。它通过在线程转储中展示任务层次结构来确保可观察性。它还可以在错误处理中实现短路。如果其中一个子任务失败,如果没有完成,其他任务将被取消。如果父任务的线程在调用之前或期间被中断 findUser()fetchOrder()join(),当范围退出时,两个分叉都将自动取消。这些使并发代码的结构更加清晰,开发人员现在可以推理和遵循代码,就好像他们在单线程环境中运行一样通读。

JEP 428:简化 Java 多线程编程的结构化并发

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注