[英]How do you access completed futures passed to CompletableFuture allOf?
I am trying to get a grip of Java 8 CompletableFuture.我正在尝试掌握 Java 8 CompletableFuture。 How can I join these to person and return them after "allOf".
我怎样才能将这些加入到人中并在“allOf”之后将它们归还。 The code under is not working but gives you an idea of what I have tried.
下面的代码不起作用,但可以让您了解我尝试过的内容。
In javascript ES6 i would do在 javascript ES6 我会做
Promise.all([p1, p2]).then(function(persons) {
console.log(persons[0]); // p1 return value
console.log(persons[1]); // p2 return value
});
My efforts in Java so far到目前为止我在Java的努力
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
@Test
public void combinePersons() throws ExecutionException, InterruptedException {
CompletableFuture<Person> p1 = CompletableFuture.supplyAsync(() -> {
return new Person("p1");
});
CompletableFuture<Person> p2 = CompletableFuture.supplyAsync(() -> {
return new Person("p1");
});
CompletableFuture.allOf(p1, p2).thenAccept(it -> System.out.println(it));
}
The CompletableFuture#allOf
method does not expose the collection of completed CompletableFuture
instances that were passed to it. CompletableFuture#allOf
方法不会公开传递给它的已完成CompletableFuture
实例的集合。
Returns a new
CompletableFuture
that is completed when all of the givenCompletableFuture
s complete.返回一个新的
CompletableFuture
,它在所有给定的CompletableFuture
完成时完成。 If any of the givenCompletableFuture
s complete exceptionally, then the returnedCompletableFuture
also does so, with aCompletionException
holding this exception as its cause.如果任何给定的
CompletableFuture
异常完成,则返回的CompletableFuture
也CompletableFuture
,CompletionException
将此异常作为其原因。 Otherwise, the results, if any, of the givenCompletableFuture
s are not reflected in the returnedCompletableFuture
, but may be obtained by inspecting them individually .否则,给定
CompletableFuture
的结果(如果有)不会反映在返回的CompletableFuture
,但可以通过单独检查它们来获得。 If noCompletableFuture
s are provided, returns aCompletableFuture
completed with the valuenull
.如果没有提供
CompletableFuture
s,则返回一个CompletableFuture
完成,值为null
。
Note that allOf
also considers futures that were completed exceptionally as completed.请注意,
allOf
还将异常完成的期货视为已完成。 So you won't always have a Person
to work with.所以你不会总是有一个
Person
可以一起工作。 You might actually have an exception/throwable.您实际上可能有异常/可抛出。
If you know the amount of CompletableFuture
s you're working with, use them directly如果您知道正在使用的
CompletableFuture
的数量,请直接使用它们
CompletableFuture.allOf(p1, p2).thenAccept(it -> {
Person person1 = p1.join();
Person person2 = p2.join();
});
If you don't know how many you have (you're working with an array or list), just capture the array you pass to allOf
如果你不知道你有多少(你正在处理一个数组或列表),只需捕获你传递给
allOf
的数组
// make sure not to change the contents of this array
CompletableFuture<Person>[] persons = new CompletableFuture[] { p1, p2 };
CompletableFuture.allOf(persons).thenAccept(ignore -> {
for (int i = 0; i < persons.length; i++ ) {
Person current = persons[i].join();
}
});
If you wanted your combinePersons
method (ignoring it's a @Test
for now) to return a Person[]
containing all the Person
objects from the completed futures, you could do如果您希望您的
combinePersons
方法( combinePersons
忽略它是一个@Test
)返回一个Person[]
包含来自已完成期货的所有Person
对象,您可以这样做
@Test
public Person[] combinePersons() throws Exception {
CompletableFuture<Person> p1 = CompletableFuture.supplyAsync(() -> {
return new Person("p1");
});
CompletableFuture<Person> p2 = CompletableFuture.supplyAsync(() -> {
return new Person("p1");
});
// make sure not to change the contents of this array
CompletableFuture<Person>[] persons = new CompletableFuture[] { p1, p2 };
// this will throw an exception if any of the futures complete exceptionally
CompletableFuture.allOf(persons).join();
return Arrays.stream(persons).map(CompletableFuture::join).toArray(Person[]::new);
}
As pointed out in @Sotirios Delimanolis's answer, the CompletableFuture is not exception friendly, which means we cannot get the result of all futures easily when exceptions happen in one or several of the futures.正如@Sotirios Delimanolis 的回答中所指出的,CompletableFuture 不是异常友好的,这意味着当一个或多个期货中发生异常时,我们无法轻松获得所有期货的结果。
As OP's question is not limited to the successful situation, in this answer, I want to make an addition to this imperfect of CompletableFuture.由于OP的问题不仅限于成功的情况,在这个答案中,我想对CompletableFuture的这个不完美做一个补充。
If we however want to know the results of all the futures, we can handle this separately when defining futures.但是,如果我们想知道所有期货的结果,我们可以在定义期货时单独处理。 For example:
例如:
CompletableFuture<Person> p1 = CompletableFuture.supplyAsync(() -> {
return new Person("p1");
});
p1.thenAccept(person -> {
// handle successful future
// for example: add p1 to success operation list
});
p1.exceptionally((exception) -> {
// handle fail future
// for example, log the parameter (not exist in this case) to create the person
System.out.println("Exception happen in creating p1");
return null;
});
and then after calling CompletableFuture.allOf(persons).join()
(Please also pay attention to the exception handling here), we can figure out which future succeeds and which future fails.然后在调用
CompletableFuture.allOf(persons).join()
之后(也请注意这里的异常处理),我们可以判断出哪个future成功,哪个future失败。
Hope this simple tip can help newcomers write solid code in real-world business systems.希望这个简单的技巧可以帮助新手在现实世界的业务系统中编写可靠的代码。
CompletableFuture.allOf(p1, p2); // .get can be ignored
List<Person> res =
List.of(p1, p2) // list of futures
.stream()
.map(future -> {
System.out.println("future " + future.join());
return future.join();
})
.collect(Collectors.toList());
Or you can fetch the values individually, using p1.get() and p2.get()或者您可以使用 p1.get() 和 p2.get() 单独获取值
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.