use*_*281 3 java-8 completable-future
我想根据特定条件跳过可完成的功能链。我尝试了在多个完成阶段进行链接时提出的解决方案,但似乎没有用。这里的代码:
@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());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Completing result1. Result: false
Completing result2. Result: true
Completing result3. Result: true
Run Code Online (Sandbox Code Playgroud)
即使“结果”可完成期货被标记为已完成,后续的可完成期货仍将执行。如何跳过Completablefuture 2和3?
您已经创建了一个依赖链,如下所示:
first
? (?)
next result
? ?
final
Run Code Online (Sandbox Code Playgroud)
该(?)是显式调用完成result.complete(…),但所有其他的完成自动发生。final通过via创建的阶段applyToEither将使用任何一个先决条件完成,以先完成者为准,但不会修改它们的行为。
原则上,任何代码可以调用complete它,而不会影响这些阶段是任可能完成final,否则阶段。取消同样适用。调用cancel一个阶段将完成该阶段,然后调用该方法,而不会影响用于构造该阶段的阶段。
所链接问题的答案会产生以下阶段
first
(?) (?)
next 1 result
? |
next 2 |
? ?
final
Run Code Online (Sandbox Code Playgroud)
关键是,初始阶段将CompletableFuture显式完成两个中的任何一个,而不触发自动完成。依赖阶段的其他链条将永远不会得到评估。由于final阶段是applyToEither,因此只有一条链的完成足以评估最终功能。它仍然不会影响先决条件阶段。
请注意thenCompose,由于函数仍会返回,因此对于由操作组成的链,可以以更简单的方式实现类似的逻辑CompletableFuture。因此,只需返回一个新CompletableFuture快捷键即可解决此问题,而该快捷键在您想要快捷方式时将永远不会完成。您甚至可以重写您的姓名首字母runAsync以thenCompose代替使用:
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();
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1347 次 |
| 最近记录: |