Java新的结构化并行模式入门指南( 三 )


这些策略将给出类似以下的输出:
复制
-- BEGIN succeedFast
BEGIN getPlanet()
BEGIN getPlanet()
Got a Planet: {"name":"Alderaan"}
org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://swapi.dev:443: Closed by interrupt
-- BEGIN failFast
BEGIN getPlanet()
BEGIN getPlanet()
BEGIN getPlanet()
BEGIN getPlanet()
BEGIN getPlanet()
Got a Planet: {"name":"Hoth"}
Got a Planet: {"name":"Tatooine"}
Error fetching planet information for ID: -1
org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://swapi.dev:443: Closed by interrupt
因此,我们拥有的是一种简单的机制,可以并发启动所有请求,然后在一个请求成功或失败时取消其余的请求 。这里,可以进行任何定制 。结构化并发文档包括一个示例,在子任务成功或失败时收集子任务结果,然后返回结果 。这很容易完成,只需通过覆盖join()方法,并观察每个任务的结果 。
StructuredTaskScope.Subtask
在我们的示例中没有看到的一件事是观察子任务的返回值 。每次StructuredTaskScope.fork()被调用时,就返回StructuredTaskScope.SubTask对象 。我们可以利用它来观察任务的状态 。比如在sc()方法中,我们可以这么做:
代码片段4. 使用StructuredTaskScope.Subtask观察状态
复制
import java.util.concurrent.StructuredTaskScope.Subtask;
import java.util.ArrayList;
void sc() throws Exception {
int[] planetIds = {1,2,3,4,5};
ArrayList<Subtask> tasks = new ArrayList<Subtask>(planetIds.length);
try (var scope = new StructuredTaskScope<Object>()) {
for (int planetId : planetIds) {
tasks.add(scope.fork(() -> getPlanet(planetId)));
}
scope.join();
}catch (Exception e){
System.out.println("Error: " + e);
}
for (Subtask t : tasks){
System.out.println("Task: " + t.state());
}
}
在这个示例中,我们将每个任务保存在ArrayList中,然后在进行join()操作之后输出它们的状态 。注意,Subtask的可用状态被定义为enum 。这个新方法将输出类似以下的内容:
复制
-- BEGIN Structured Concurrency
BEGIN getPlanet()
BEGIN getPlanet()
BEGIN getPlanet()
BEGIN getPlanet()
BEGIN getPlanet()
Got a Planet: {"name":"Dagobah"}
Got a Planet: {"name":"Hoth"}
Got a Planet: {"name":"Tatooine"}
Got a Planet: {"name":"Yavin IV"}
Got a Planet: {"name":"Alderaan"}
Task: SUCCESS
Task: SUCCESS
Task: SUCCESS
Task: SUCCESS
Task: SUCCESS
结论在虚拟线程和结构化并发之间,Java开发者拥有一种引人注目的新机制 , 可以将几乎所有代码分解成并发任务,不会有太大的开销 。上下文和需求很重要,所以不要仅仅因为存在这些新的并发工具就使用它们 。与此同时,这种组合确实提供了一些强大的力量 。一旦您遇到出现许多任务的瓶颈时,您可以轻松地将它们全部交给虚拟线程引擎,该引擎将找到编排它们的最佳方法 。具有结构化并发的新线程模式还使您易于定制和微调这种行为 。
至于开发者将来如何在我们的应用程序、框架和服务器中使用这些新的并发功能 , 值得我们拭目以待 。
小知识:结构化并发中的线程树
结构化并发包括对调试和理解线程之间关系的支持 。特别是,结构化并发将所有线程关联到树结构中,作用域位于根 。这样一来 , 查看线程之间的关系就变得很简单,即便使用嵌套作用域也是如此 。说明文档提供了一个好的示例,表明如何使用Java诊断命令(jcmd)实用程序,将线程的运行时布局转储到控制台 。
原文标题:Get started with Java's new structured concurrency model , 作者:Matthew Tyson




推荐阅读