Java 8 基于条件的可完成未来的快捷链
我想跳过基于特定条件的完整期货链。我尝试了当时提出的解决方案,但似乎不起作用。下面是代码:Java 8 基于条件的可完成未来的快捷链,java-8,completable-future,Java 8,Completable Future,我想跳过基于特定条件的完整期货链。我尝试了当时提出的解决方案,但似乎不起作用。下面是代码: @RunWith(JUnit4.class) public class ExceptionHandlingTests { @Test public void test1() { CompletableFuture<Integer> result = new CompletableFuture<>(); CompletableFuture.runAsync(() -&
@RunWith(JUnit4.class)
public class ExceptionHandlingTests {
@Test
public void test1() {
CompletableFuture<Integer> result = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
System.out.println("Completing result1. Result: " + result.isDone());
result.complete(10);
}).thenCompose(x -> {
System.out.println("Completing result2. Result: " + result.isDone());
result.complete(10);
return CompletableFuture.completedFuture(5);
}).thenCompose(x -> {
System.out.println("Completing result3. Result: " + result.isDone());
result.complete(10);
return CompletableFuture.completedFuture(5);
}).applyToEither(result, Function.identity());
}
}
即使“结果”completablefuture标记为completed,后续completablefutures仍将执行。如何跳过Completablefuture 2和3?您已经创建了如下依赖关系链:
首先
↓ (↘)
下一个结果
↓ ↙
最终的
(↘)
是一个显式的完成调用结果。完成(…)
,但所有其他完成都会自动进行。通过ApplyTo任一
创建的最终
阶段将使用任一先决条件(以先完成的为准)完成,但不会修改它们的行为
原则上,任何代码都可以在其上调用complete
,而不会影响可能在其他情况下完成final
阶段的任何一个阶段。这同样适用于取消。在阶段上调用cancel
将完成该阶段,您可以在该阶段上调用该方法,而不会影响用于构建它的阶段
链接问题的答案创建了如下阶段
首先
(↙) (↘)
下一个1结果
↓ |
下一个2|
↘ ↙
最终的
关键点是,初始阶段将明确完成两个CompletableFuture
中的任何一个,而不会触发自动完成。其他相关阶段链将永远不会得到评估。由于最终
阶段是一个applytoother
,因此仅完成其中一个链就足以进行评估最终功能。它仍然不影响先决条件阶段
请注意,对于由和compose
操作组成的链,您可以以更简单的方式实现类似的逻辑,因为您的函数无论如何都会返回一个CompletableFuture
。因此,只需返回一个新的CompletableFuture
,当您想要快捷方式时将永远无法完成,就可以解决问题。您甚至可以重写初始的runAsync
以使用然后编写:
for(int shortCutAt: IntStream.range(0, 4).toArray()) {
System.out.println("Example execution with "
+(shortCutAt==0? "no shortcut": "shortcut at "+shortCutAt));
CompletableFuture<Integer> result = new CompletableFuture<>();
CompletableFuture.completedFuture(null).thenCompose(justVoid -> { // runAsync
System.out.println("Completing result1. Result: " + result.isDone());
if(shortCutAt == 1) { result.complete(10); return new CompletableFuture<>(); }
return CompletableFuture.completedFuture(justVoid);
}).thenCompose(x -> {
System.out.println("Completing result2. Result: " + result.isDone());
if(shortCutAt == 2) { result.complete(10); return new CompletableFuture<>(); }
return CompletableFuture.completedFuture(5);
}).thenCompose(x -> {
System.out.println("Completing result3. Result: " + result.isDone());
if(shortCutAt == 3) { result.complete(10); return new CompletableFuture<>(); }
return CompletableFuture.completedFuture(5);
})
.applyToEither(result, Function.identity())
.thenAccept(fr -> System.out.println("final result: "+fr));
System.out.println();
}
为什么您希望跳过它们?这些阶段与结果
完全无关。我认为这是ApplyTorth基于早期堆栈溢出anwer所做的。我在描述中提供了链接。在这种情况下,是否有方法跳过其余的可完成未来?在链接的答案中,有两个未来,只有一个未来m将被完成。由于另一个从未完成,因此它的相关阶段不会被计算。applytoother
的属性只是不等待另一个。但是applytoother
单独不足以阻止阶段的计算。太棒了。谢谢Holger。谢谢@Holger。我重构了解决方案以提高重用性可扩展性。将该方法封装在一个名为ShortCircuitCF
的简单类中,其中包含传播结果或完成可完成未来的方法
for(int shortCutAt: IntStream.range(0, 4).toArray()) {
System.out.println("Example execution with "
+(shortCutAt==0? "no shortcut": "shortcut at "+shortCutAt));
CompletableFuture<Integer> result = new CompletableFuture<>();
CompletableFuture.completedFuture(null).thenCompose(justVoid -> { // runAsync
System.out.println("Completing result1. Result: " + result.isDone());
if(shortCutAt == 1) { result.complete(10); return new CompletableFuture<>(); }
return CompletableFuture.completedFuture(justVoid);
}).thenCompose(x -> {
System.out.println("Completing result2. Result: " + result.isDone());
if(shortCutAt == 2) { result.complete(10); return new CompletableFuture<>(); }
return CompletableFuture.completedFuture(5);
}).thenCompose(x -> {
System.out.println("Completing result3. Result: " + result.isDone());
if(shortCutAt == 3) { result.complete(10); return new CompletableFuture<>(); }
return CompletableFuture.completedFuture(5);
})
.applyToEither(result, Function.identity())
.thenAccept(fr -> System.out.println("final result: "+fr));
System.out.println();
}