【发布时间】:2017-03-21 14:25:18
【问题描述】:
我正在学习 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());
}
}
【问题讨论】:
-
链接示例中没有
main。在 StackOverflow 上,您应该将代码包含在问题本身中。无论如何,假设你的意思是测试方法,你看过thenRun的文档吗? -
@RealSkeptic:我说的是名为“main”的线程。
-
很好,但是,您仍然没有等待任何东西,那么您希望调用线程做什么?它只是终止。
-
@RealSkeptic:嗯,这个 repo 不是我的,而是由 nurkiewicz 编写的,我认为他是关于 CompletableFutures 等 youtube 视频的一位非常好的导师。这就是为什么我有点对此感到困惑。我会问他的。
-
@RealSkeptic 我向 gitrepo 的作者建议了一个拉取请求,并将代码添加到这篇文章中。
标签: java multithreading java-8 completable-future