for循环等待所有CompletableFutures给出结果,并将结果添加到int
For loop wait for all CompletableFutures to give result, and add result to int
我有一个方法 getCount(id) returns 来自数据库的整数,作为 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);
这会出错,因为您不能在 thenAccept 中将一个整数与另一个整数相加,因为它是一个消费者。有什么方法可以做到这一点?
注意传递给thenAccept
的函数可以由任意线程执行,所以谢天谢地,Java不允许他们修改局部多变的。当您将变量更改为堆上的字段时,编译器会接受它,但结果会完全损坏。
最简单的解决方案是
int totalCount = 0;
for(String id: API.getIDs()) {
totalCount += OtherAPI.getCount(id).join();
}
它只是等待每个值的可用性,在本地对它们求和。根据 OtherAPI.getCount(…)
调用封装的操作,这甚至可能是最有效的解决方案。
但是当这些操作需要很长时间并且可以真正 运行 并行时,即不依赖于内部共享资源,在所有操作开始之前不等待可能是有益的。
你可以这样做
CompletableFuture<Integer> result = CompletableFuture.completedFuture(0);
for(String id: API.getIDs()) {
result = result.thenCombine(OtherAPI.getCount(id), Integer::sum);
}
System.out.println(result.join());
这里,整个循环都是wait-free。它将安排求和操作,在完成两个操作后完成。然后,只有最后的join
调用才会等待最后的结果。至此,所有的异步操作都已经提交。
我有一个方法 getCount(id) returns 来自数据库的整数,作为 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);
这会出错,因为您不能在 thenAccept 中将一个整数与另一个整数相加,因为它是一个消费者。有什么方法可以做到这一点?
注意传递给thenAccept
的函数可以由任意线程执行,所以谢天谢地,Java不允许他们修改局部多变的。当您将变量更改为堆上的字段时,编译器会接受它,但结果会完全损坏。
最简单的解决方案是
int totalCount = 0;
for(String id: API.getIDs()) {
totalCount += OtherAPI.getCount(id).join();
}
它只是等待每个值的可用性,在本地对它们求和。根据 OtherAPI.getCount(…)
调用封装的操作,这甚至可能是最有效的解决方案。
但是当这些操作需要很长时间并且可以真正 运行 并行时,即不依赖于内部共享资源,在所有操作开始之前不等待可能是有益的。
你可以这样做
CompletableFuture<Integer> result = CompletableFuture.completedFuture(0);
for(String id: API.getIDs()) {
result = result.thenCombine(OtherAPI.getCount(id), Integer::sum);
}
System.out.println(result.join());
这里,整个循环都是wait-free。它将安排求和操作,在完成两个操作后完成。然后,只有最后的join
调用才会等待最后的结果。至此,所有的异步操作都已经提交。