我有一个方法getCount(id),它从数据库返回一个整数,作为CompletableFuture。我想遍历所有id,并获得所有它们的结果,并将它们添加到一个全局int。然后我想用那个int做些事情:
int totalCount;
for (String id : API.getIDs()) {
//OtherAPI.getCount(id) will return the CompletableFuture<Integer>
OtherAPI.getCount(id).thenAccept(count -> totalCount += count);
}
System.out.println("" + totalCount);
这会给出一个错误,因为您不能在Accept中将一个整数添加到另一个整数,因为它是一个消费者。怎么做?
请注意,传递给 thenAccept
的函数可以由任意线程执行,因此值得庆幸的是,Java 不允许它们修改局部变量。当您将变量更改为堆上的字段时,编译器将接受它,但结果将完全中断。
最简单的解决方案是
int totalCount = 0;
for(String id: API.getIDs()) {
totalCount += OtherAPI.getCount(id).join();
}
它只是等待每个值的可用性,在本地对它们求和。根据< code > other API . get count(…)调用封装的操作,这甚至可能是最有效的解决方案。
但是,当这些操作需要很长时间并且能够真正并行运行时,即不依赖于内部共享资源,那么在开始所有操作之前不要等待可能是有益的。
你可以这样做
CompletableFuture<Integer> result = CompletableFuture.completedFuture(0);
for(String id: API.getIDs()) {
result = result.thenCombine(OtherAPI.getCount(id), Integer::sum);
}
System.out.println(result.join());
在这里,循环完全无需等待。它将安排求和操作,在完成两个操作后完成。然后,只有最后的加入
调用将等待最终结果。此时,所有异步操作都已提交。