Java 推迟应用同步执行
我有下面的场景Java 推迟应用同步执行,java,java-8,completable-future,Java,Java 8,Completable Future,我有下面的场景 CompletableFuture<T> result = CompletableFuture.supplyAsync(task, executor); result.thenRun(() -> { ... }); // .... // after some more code, based on some condition I attach the thenApply() to result. if ( x == 1) {
CompletableFuture<T> result = CompletableFuture.supplyAsync(task, executor);
result.thenRun(() -> {
...
});
// ....
// after some more code, based on some condition I attach the thenApply() to result.
if ( x == 1) {
result.thenApplyAsync(t -> {
return null;
});
}
问题是,如果CompletableFuture线程在主线程到达ThenApplySync之前完成执行,该怎么办?是否应将完整的未来结果附加到应用中。i、 e是否应在定义CompletableFuture.SupplySync本身时声明回调
还有,执行的顺序是什么?然后运行始终在应用之后执行
使用这种策略有什么缺点吗?您似乎遗漏了一个要点。当你链接一个依赖函数时,你不会改变你调用链接方法的未来 相反,这些方法中的每一个都返回一个表示依赖操作的新完成阶段 由于要将两个相关操作附加到结果,这两个操作表示传递给SupplySync的任务,因此这两个操作之间没有关系。它们可以以任意顺序运行,甚至可以同时在不同的线程中运行 由于您没有将ApplySync返回的future存储在任何位置,因此其计算结果将丢失。假设您的函数返回与T相同类型的结果,您可以使用
if(x == 1) {
result = result.thenApplyAsync(t -> {
return null;
});
}
用新的未来替换可能已完成的未来,新的未来仅在指定函数的结果已被评估时完成。通过thenRun在原始future注册的runnable仍然不依赖于此新future。请注意,不带执行器的ApplyAsync将始终使用默认执行器,无论使用哪个执行器来完成另一个未来
如果要确保在任何其他阶段之前已成功执行Runnable,可以使用
CompletableFuture<T> result = CompletableFuture.supplyAsync(task, executor);
CompletableFuture<Void> thenRun = result.thenRun(() -> {
//...
});
result = result.thenCombine(thenRun, (t,v) -> t);
但在这里,即使在包括取消的例外情况下,代码也将始终执行。如果只想在成功的情况下执行代码,则必须检查throwable是否为null
如果要确保runnable在两个操作之后运行,最简单的策略是在定义最终完成阶段时,将其链接到If语句之后:
if(x == 1) {
result = result.thenApplyAsync(t -> {
return null;
});
}
result.thenRun(() -> {
//...
});
如果这不是一个选项,您将需要一个不完整的未来,您可以根据以下任一结果完成:
CompletableFuture<T> result = CompletableFuture.supplyAsync(task, executor);
//...
CompletableFuture<T> finalStage = new CompletableFuture<>();
finalStage.thenRun(() -> {
//...
});
// ...
if(x == 1) {
result = result.thenApplyAsync(t -> {
return null;
});
}
result.whenComplete((v,t) -> {
if(t != null) finalStage.completeExceptionally(t); else finalStage.complete(v);
});
最后阶段最初没有定义的完成方式,但我们仍然可以链接相关的操作。一旦我们知道了实际的未来,我们就可以链上一个处理程序,它将以我们得到的任何结果完成我们的最后阶段
最后,不带…Async的方法(如thenRun)对计算线程的控制最少。它们可能会在将来完成的任何线程中执行,就像您的示例中的一个executor线程,但也会直接在调用thenRun的线程中执行,更不直观的是,在您的原始示例中,runnable可能会在不相关的ThenApplySync调用中执行。谢谢。是否有任何方法确保在应用同步之后执行Run或RunAySNC?我知道在这种情况下,它们可以并行运行。我只想在异步运行之后在运行中设置某些值。谢谢。isDone在第一个completionstage之后或在所有依赖项完成之后返回true?@ulab它取决于调用isDone的未来。如果您有依赖链,请使用最后一个,即运行返回的依赖链,以确定整个操作是否已完成。否则,请始终记住,您有一组单独的CompletableFuture实例,每个实例都有自己的完成状态。这正是我想要的!
CompletableFuture<T> result = CompletableFuture.supplyAsync(task, executor);
//...
CompletableFuture<T> finalStage = new CompletableFuture<>();
finalStage.thenRun(() -> {
//...
});
// ...
if(x == 1) {
result = result.thenApplyAsync(t -> {
return null;
});
}
result.whenComplete((v,t) -> {
if(t != null) finalStage.completeExceptionally(t); else finalStage.complete(v);
});