我正在Java 1.8中学习CompletableFuture
并且无法理解allOf
。似乎主线程不等待任何CompletableFuture
完成。
有关我正在测试的示例,请参阅https://github.com/nurkiewicz/reactive/blob/master/src/test/java/be/more/reactive/S03_AllOf.java。
测试作业在打印结果之前完成。
有两种(丑陋?)方法可以避免这种情况:1)在主线程上设置超时并等待两者完成。 2)在最后设置.get()
,它将成为阻塞任务。
为什么会这样?
代码片段:
package be.more.reactive;
import be.more.reactive.util.BaseTest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
public class S03_AllOf extends BaseTest {
private static final Logger log = LoggerFactory.getLogger(S03_AllOf.class);
private final CompletableFuture<String> futureResult1 = getFutureQueryResult("1"); //.exceptionally() ??
private final CompletableFuture<String> futureResult2 = getFutureQueryResult("2");
private final CompletableFuture<String> futureResult3 = getFutureQueryResult("3");
private final CompletableFuture<String> futureResult4 = getFutureQueryResult("4");
@Test
public void allOf() throws Exception {
final CompletableFuture<Void> futureResult = CompletableFuture.allOf( //Void ?? I want List<String>
futureResult1, futureResult2, futureResult3, futureResult4
);
// futureResult.thenAccept((Void vd) -> vd.??) //no, it won't work
futureResult.thenRun(() -> {
try {
log.debug("Query result 1: '{}'", futureResult1.get());
log.debug("Query result 2: '{}'", futureResult2.get());
log.debug("Query result 3: '{}'", futureResult3.get());
log.debug("Query result 4: '{}'", futureResult4.get()); //a lot of manual work
log.debug("Now do on complete"); //handling onComplete
} catch (Exception e) {
log.error("", e);
}
});
}
}
在BaseTest中:
protected CompletableFuture<String> getFutureQueryResult(final String queryId) {
return CompletableFuture.supplyAsync(
() -> db.apply(new Query(queryId))
);
}
在DB.java中
package be.more.reactive.db;
import java.util.concurrent.TimeUnit;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang3.RandomUtils.nextInt;
import static org.apache.commons.lang3.RandomUtils.nextLong;
public class DB {
public String apply(Query query) {
try {
TimeUnit.SECONDS.sleep(nextLong(2, 4));
} catch (InterruptedException e) {
e.printStackTrace();
}
return String.format("%s_%s", randomAlphabetic(nextInt(4, 12)), query.getId());
}
}
答案 0 :(得分:1)
来自Javadoc
返回在所有给定的CompletableFutures完成时完成的新CompletableFuture。
Future
是一个异步任务,在您调用get
之前不会阻塞(只有在任务仍在运行时才会阻塞)。
在这种情况下,CompleteableFuture
是所有Future
的复合CompletableFuture
。此未来仍将是阻止异步调用,您必须调用get
或join
等待所有期货完成。再次,来自javadoc
在继续执行程序之前CompletableFutures,如:
CompletableFuture.allOf(c1, c2, c3).join();
。
在我看来,你的(2)解决方案既不是丑陋也不是意想不到的功能。