CompletableFuture 如果保存到变量则不起作用
CompletableFuture doesn't work if it saved to variable
为什么在配置步骤之前将未来保存到变量时它不起作用?
@Test
void simple() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(this::throwException)
.exceptionally(throwable -> HANDLED);
assertEquals(HANDLED, future.join());
}
@Test
void withVar() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(this::throwException);
future.exceptionally(throwable -> HANDLED);
assertEquals(HANDLED, future.join());
}
private String throwException() {
if (true) {
throw new RuntimeException(FAIL);
}
return SUCCESS;
}
simple()
可以,但是withVar()
不行:
java.util.concurrent.CompletionException: java.lang.RuntimeException: FAIL
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1702)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1692)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)`
Caused by: java.lang.RuntimeException: FAIL
at ru.dionisis.resttest.ComplitableFutureTest.throwException(ComplitableFutureTest.java:35)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
... 6 more`
类似的问题出现在 RestTemplateBuilder
,当我想在一个字段中创建一个可选的初始值时
来自 the JavaDoc for exceptionally
:“Returns 一个 new CompletableFuture...”。它不会改变它所调用的 CompleteableFuture。
您正在创建一个具有新行为的新 CompleteableFuture,然后将其丢弃,然后 join
在没有该行为的原始 CompleteableFuture 上。
这就像说 String::toUpperCase
在这个例子中不起作用。它确实有效,但结果被丢弃了。
String foo = "bar";
foo.toUpperCase();
assertEquals("BAR", foo);
为什么在配置步骤之前将未来保存到变量时它不起作用?
@Test
void simple() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(this::throwException)
.exceptionally(throwable -> HANDLED);
assertEquals(HANDLED, future.join());
}
@Test
void withVar() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(this::throwException);
future.exceptionally(throwable -> HANDLED);
assertEquals(HANDLED, future.join());
}
private String throwException() {
if (true) {
throw new RuntimeException(FAIL);
}
return SUCCESS;
}
simple()
可以,但是withVar()
不行:
java.util.concurrent.CompletionException: java.lang.RuntimeException: FAIL
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1702)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1692)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)`
Caused by: java.lang.RuntimeException: FAIL
at ru.dionisis.resttest.ComplitableFutureTest.throwException(ComplitableFutureTest.java:35)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
... 6 more`
类似的问题出现在 RestTemplateBuilder
,当我想在一个字段中创建一个可选的初始值时
来自 the JavaDoc for exceptionally
:“Returns 一个 new CompletableFuture...”。它不会改变它所调用的 CompleteableFuture。
您正在创建一个具有新行为的新 CompleteableFuture,然后将其丢弃,然后 join
在没有该行为的原始 CompleteableFuture 上。
这就像说 String::toUpperCase
在这个例子中不起作用。它确实有效,但结果被丢弃了。
String foo = "bar";
foo.toUpperCase();
assertEquals("BAR", foo);