嵌套期货未执行
我遇到了一个奇怪的情况。我与CompletableFuture
摆弄和运行下面的代码时,我会有意想不到的效果:嵌套期货未执行
public static void main(String[] args) {
CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<Object>>>>>> completableFutureCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("first");
return CompletableFuture.supplyAsync(() -> {
System.out.println("second");
return CompletableFuture.supplyAsync(() -> {
System.out.println("third");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fourth");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fifth");
return CompletableFuture.completedFuture(null);
});
});
});
});
});
completableFutureCompletableFuture.get();
}
没有异常被抛出(使用exceptionally
即使)和我看到的是,控制台输出
first
second
third // appears sometimes
现在,很明显,这段代码并没有真正的产值,但是这是代码的嵌套数量未知的情况,其中每个或其中一些创建了不会执行的嵌套。
任何解释(和示例如何修复),将不胜感激
这不起作用的原因是因为在你的简单测试中,虚拟机在所有任务完成之前退出。
当您拨打completableFutureCompletableFuture.get()
时,只保证期货的第一次嵌套完成。 VM退出,并且所有线程都被终止。
换句话说,第一个嵌套的未来仍然可能“未完成”,因为它的线程可能仍然很忙。但是,当您尝试使用get
获得结果时,它当然会一直等到它完成并且会按预期工作。试试吧:
completableFutureCompletableFuture.get().get().get().get().get()
...然后你强制所有的期货已经完成,一切都按预期工作。
谢谢。有效。 –
只是测试这和它的作品。我认为为什么不能为你工作的原因是因为你用主要方法运行,而你没有等待完成。在你的代码完成后,我做了一个Thread.sleep(1000)
。最好的办法是终止:completableFutureCompletableFuture.get().get().get().get().get()
发生这种情况是因为你的CompletableFuture是异步执行的,但是你的程序在第五次调用发生之前就终止了(我假设你在一个main中运行它并在创建你的未来之后返回)。
正如你可能不知道未来有多少未来(由于类型擦除)。你可能想要执行一个递归的.get()。
请参见:
public static void main(String[] args) throws InterruptedException, ExecutionException {
CompletableFuture<?> futures = getFutures();
recursiveGet(futures);
System.out.println("finished");
}
public static CompletableFuture<?> getFutures() {
CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<Object>>>>>> compositeCompletable = CompletableFuture.supplyAsync(() -> {
System.out.println("first");
return CompletableFuture.supplyAsync(() -> {
System.out.println("second");
return CompletableFuture.supplyAsync(() -> {
System.out.println("third");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fourth");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fifth");
return CompletableFuture.completedFuture(null);
});
});
});
});
});
return compositeCompletable;
}
public static void recursiveGet(Future<?> future) throws InterruptedException, ExecutionException{
Object result = future.get();
if(result instanceof Future){
recursiveGet((Future<?>) result);
}
}
返回
first
second
third
fourth
fifth
finished
你可能不希望有嵌套期货这样的。你应该看看['ThenCompose [Async]()'](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#thenCompose-java.util .function.Function-)。 –