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();
}