jdk8 之后 Future、CompletableFuture 的新增方法
-
- [Future jdk19](#Future jdk19)
- [CompletableFuture jdk9](#CompletableFuture jdk9)
-
- defaultExecutor
- newIncompleteFuture
- copy
- minimalCompletionStage
- completeAsync
- orTimeout、completeOnTimeout
- [static delayedExecutor](#static delayedExecutor)
- [static completedStage、failedFuture、failedStage](#static completedStage、failedFuture、failedStage)
- [CompletableFuture jdk12](#CompletableFuture jdk12)
- 参考
Future jdk19
任务状态
java
/**
* Represents the computation state.
* @since 19
*/
enum State {
/**
* 未完成
*/
RUNNING,
/**
* 正常结束,可获取结果
*/
SUCCESS,
/**
* 异常结束,获取结果会抛出异常
*/
FAILED,
/**
* 被取消了,获取结果会抛出异常 CancellationException
*/
CANCELLED
}
java
default State state()
四个任务状态,以及一个获取状态的方法
测试 RUNNING、SUCCESS
java
static void test1() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
TimeUnit.SECONDS.sleep(1);
return "ok";
});
IO.println(future.state());
String result = future.get();
IO.println(result);
IO.println(future.state());
}
RUNNING
ok
FAILED
测试 FAILED
java
static void test2() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
TimeUnit.SECONDS.sleep(1);
throw new RuntimeException();
});
IO.println(future.state());
TimeUnit.SECONDS.sleep(2);
IO.println(future.state());
future.get();
}
RUNNING
FAILED
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:124)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:193)
at com.zbs.jdk.FutureTest1.test2(FutureTest1.java:42)
at com.zbs.jdk.FutureTest1.main(FutureTest1.java:15)
Caused by: java.lang.RuntimeException
at com.zbs.jdk.FutureTest1.lambda$test2$0(FutureTest1.java:36)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
at java.base/java.lang.Thread.run(Thread.java:1474)
测试 CANCELLED
java
static void test3() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
TimeUnit.SECONDS.sleep(1);
return "ok";
});
IO.println(future.state());
future.cancel(true);
IO.println(future.state());
String result = future.get();
IO.println(result);
}
RUNNING
CANCELLED
Exception in thread "main" java.util.concurrent.CancellationException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:123)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:193)
at com.zbs.jdk.FutureTest1.test3(FutureTest1.java:56)
at com.zbs.jdk.FutureTest1.main(FutureTest1.java:16)
resultNow
java
default V resultNow()
返回任务正常完成时的结果,不会阻塞等待,若任务状态不是 SUCCESS 会抛出异常。该方法适用于调用者已知任务已成功完成的情况。
测试 SUCCESS
java
static void test1() {
ExecutorService executor = Executors.newCachedThreadPool();
List<Future<?>> futures = new ArrayList<>(3);
futures.add(executor.submit(() -> "task1 ok"));
futures.add(executor.submit(() -> {
throw new RuntimeException();
}));
futures.add(executor.submit(() -> "task3 ok"));
List<?> results = futures.stream()
.filter(f -> f.state() == Future.State.SUCCESS)
.map(Future::resultNow)
.toList();
IO.println(results);
}
[task1 ok, task3 ok]
如果任务未正常完成,会抛异常。
测试 RUNNING
java
static void test2() throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
});
TimeUnit.SECONDS.sleep(1);
IO.println(future.resultNow());
}
Exception in thread "main" java.lang.IllegalStateException: Task has not completed
at java.base/java.util.concurrent.FutureTask.resultNow(FutureTask.java:225)
at com.zbs.jdk.FutureTest2.test2(FutureTest2.java:47)
at com.zbs.jdk.FutureTest2.main(FutureTest2.java:16)
测试 FAILED
java
static void test3() throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(() -> {
throw new RuntimeException();
});
TimeUnit.SECONDS.sleep(1);
IO.println(future.resultNow());
}
Exception in thread "main" java.lang.IllegalStateException: Task completed with exception
at java.base/java.util.concurrent.FutureTask.resultNow(FutureTask.java:221)
at com.zbs.jdk.FutureTest2.test3(FutureTest2.java:58)
at com.zbs.jdk.FutureTest2.main(FutureTest2.java:17)
测试 CANCELLED
java
static void test4() {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
});
future.cancel(true);
IO.println(future.resultNow());
}
Exception in thread "main" java.lang.IllegalStateException: Task was cancelled
at java.base/java.util.concurrent.FutureTask.resultNow(FutureTask.java:223)
at com.zbs.jdk.FutureTest2.test4(FutureTest2.java:73)
at com.zbs.jdk.FutureTest2.main(FutureTest2.java:18)
exceptionNow
java
default Throwable exceptionNow()
与 resultNow() 相反,返回任务异常完成时抛出的异常,不会阻塞等待,若任务状态不是 FAILED 会抛出异常。适用于调用者知道任务已经完成但抛出异常的情况(不包含任务被取消的情况)。
测试 FAILED
java
static void test1() {
ExecutorService executor = Executors.newCachedThreadPool();
List<Future<?>> futures = new ArrayList<>(3);
futures.add(executor.submit(() -> "task1 ok"));
futures.add(executor.submit(() -> {
throw new RuntimeException("task 2 ex");
}));
futures.add(executor.submit(() -> "task3 ok"));
List<?> results = futures.stream()
.filter(f -> f.state() == Future.State.FAILED)
.map(Future::exceptionNow)
.toList();
IO.println(results);
}
[java.lang.RuntimeException: task 2 ex]
java
static void test3() throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(() -> {
throw new RuntimeException();
});
TimeUnit.SECONDS.sleep(1);
IO.println(future.state());
IO.println(future.exceptionNow());
}
FAILED
java.lang.RuntimeException
调用方法时,如果任务未以抛出异常的方式完成,则会抛出异常。
测试 RUNNING
java
static void test2() throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
});
TimeUnit.SECONDS.sleep(1);
IO.println(future.state());
IO.println(future.exceptionNow());
}
RUNNING
Exception in thread "main" java.lang.IllegalStateException: Task has not completed
at java.base/java.util.concurrent.FutureTask.exceptionNow(FutureTask.java:243)
at com.zbs.jdk.FutureTest3.test2(FutureTest3.java:52)
at com.zbs.jdk.FutureTest3.main(FutureTest3.java:17)
测试 SUCCESS
java
static void test4() throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> "ok");
TimeUnit.SECONDS.sleep(1);
IO.println(future.state());
IO.println(future.exceptionNow());
}
SUCCESS
Exception in thread "main" java.lang.IllegalStateException: Task completed with a result
at java.base/java.util.concurrent.FutureTask.exceptionNow(FutureTask.java:236)
at com.zbs.jdk.FutureTest3.test4(FutureTest3.java:72)
at com.zbs.jdk.FutureTest3.main(FutureTest3.java:19)
测试 CANCELLED
java
static void test5() {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
});
future.cancel(true);
IO.println(future.state());
IO.println(future.exceptionNow());
}
CANCELLED
Exception in thread "main" java.lang.IllegalStateException: Task was cancelled
at java.base/java.util.concurrent.FutureTask.exceptionNow(FutureTask.java:241)
at com.zbs.jdk.FutureTest3.test5(FutureTest3.java:88)
at com.zbs.jdk.FutureTest3.main(FutureTest3.java:20)
CompletableFuture jdk9
CompletableFuture 实现了 Future 接口,所以也具备上述的功能。
关于调用线程的情况如下:
-
大多数不以 Async 结尾的方法(比如
thenRun、thenApply、exceptionally、exceptionallyCompose)的执行线程:如果执行本方法时前一个阶段已经执行结束,则会在调用本方法线程中阻塞的执行本方法的逻辑,如果前一个阶段没有执行结束,则会在执行前一个阶段的线程中执行本方法的逻辑。 -
xxAsync(...)方法的执行线程是默认线程池,也就是ForkJoinPool.asyncCommonPool()。 -
xxAsync(..., Executor executor)方法的执行线程是线程池executor。
以下不再赘述。
defaultExecutor
java
public Executor defaultExecutor() {
return ASYNC_POOL;
}
返回 async 方法不指定 Executor 时的默认 Executor。默认实现返回 ForkJoinPool.asyncCommonPool()。
java
static void main() {
IO.println(CompletableFuture.completedFuture(1).defaultExecutor());
}
java.util.concurrent.ForkJoinPool@5674cd4d[Running, parallelism = 15, size = 0, active = 0, running = 0, steals = 0, tasks = 0, submissions = 0]
newIncompleteFuture
java
public <U> CompletableFuture<U> newIncompleteFuture() {
return new CompletableFuture<U>();
}
返回一个新的未完成的 CompletableFuture。此方法在子类化 CompletableFuture 时特别有用,主要是因为它在几乎所有返回新 CompletionStage 的方法中内部使用,允许子类控制这些方法返回的子类型。
copy
java
public CompletableFuture<T> copy()
将前一阶段的 CompletableFuture 复制为一个新的 CompletableFuture。未调用 complete()、completeExceptionally()、cancel()、obtrudeValue()、obtrudeException()、completeAsync()、orTimeout()、completeOnTimeout() 等方法手动完成时的默认行为是:
-
如果前一阶段正常完成,则此阶段也会以相同的返回值完成。
-
如果前一阶段异常完成,则此阶段也会以相同的
CompletionException异常完成。 -
当此阶段执行时,前一阶段的任务逻辑不会再被执行一遍,
copy()等价于thenApply(x -> x)。
此方法可用于"防御性复制",避免后续操作对于原实例的修改(例如调用上述手动完成的方法),同时仍能在 CompletableFuture 实例上安排后续的依赖操作。
防御性复制
假设在下单时,保存完订单信息后发送 MQ。
java
static void placeOrder() {
CompletableFuture<Integer> saveOrderFuture = saveOrder();
}
static CompletableFuture<Integer> saveOrder() {
// saveOrder
CompletableFuture<Integer> saveOrderFuture = CompletableFuture.supplyAsync(() -> {
int orderId = 1;
IO.println("start saveOrder: " + orderId);
Utils.sleep(1);
IO.println("completed saveOrder: " + orderId);
return orderId;
});
// sendMQ
sendMQ(saveOrderFuture);
return saveOrderFuture;
}
static void sendMQ(CompletableFuture<Integer> saveOrderFuture) {
saveOrderFuture.thenAcceptAsync(id -> IO.println("sendMQ: " + id));
}
正确的输出如下:
start saveOrder: 1
completed saveOrder: 1
sendMQ: 1
假设有客户代码调用了 saveOrderFuture.complete(2);
java
static void placeOrder() {
CompletableFuture<Integer> saveOrderFuture = saveOrder();
// !!!
saveOrderFuture.complete(2);
}
这会导致 MQ 发送的 orderId 为错误的值 2。
start saveOrder: 1
sendMQ: 2
completed saveOrder: 1
如果 saveOrder 使用 copy() 返回 saveOrderFuture 的副本就可以避免上述的错误:
java
static CompletableFuture<Integer> saveOrder() {
// saveOrder
CompletableFuture<Integer> saveOrderFuture = CompletableFuture.supplyAsync(() -> {
int orderId = 1;
IO.println("start saveOrder: " + orderId);
Utils.sleep(1);
IO.println("completed saveOrder: " + orderId);
return orderId;
});
// sendMQ
sendMQ(saveOrderFuture);
// copy
return saveOrderFuture.copy();
}
start saveOrder: 1
completed saveOrder: 1
sendMQ: 1
测试正常完成
java
static void test1() throws ExecutionException, InterruptedException {
CompletableFuture<Object> f1 = CompletableFuture.supplyAsync(() -> {
IO.println("task running");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return new Object();
});
CompletableFuture<Object> f2 = f1.copy();
Object r1 = f1.get();
Object r2 = f2.get();
IO.println("f1 result: " + r1);
IO.println("f2 result: " + r2);
IO.println("r1 == r2: " + (r1 == r2));
IO.println("f1 state: " + f1.state());
IO.println("f2 state: " + f2.state());
}
task running 只打印了一次,说明任务逻辑不会被重复执行。
r1 == r2: true 说明新老 CompletableFuture 共享返回值。
新老 CompletableFuture 状态都是 SUCCESS。
task running
f1 result: java.lang.Object@38af3868
f2 result: java.lang.Object@38af3868
r1 == r2: true
f1 state: SUCCESS
f2 state: SUCCESS
测试异常完成
java
static void test2() {
CompletableFuture<Object> f1 = CompletableFuture.supplyAsync(() -> {
IO.println("task running");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
throw new RuntimeException("timestamp: " + System.currentTimeMillis());
});
CompletableFuture<Object> f2 = f1.copy();
Throwable e1 = getException(f1);
Throwable e2 = getException(f2);
IO.println("f1 result: " + e1);
IO.println("f2 result: " + e2);
IO.println("e1 == e2: " + (e1 == e2));
IO.println("e1.cause == e2.cause: " + (e1.getCause() == e2.getCause()));
IO.println("f1 state: " + f1.state());
IO.println("f2 state: " + f2.state());
}
static Throwable getException(CompletableFuture<?> f1) {
try {
f1.join();
} catch (Exception e) {
return e;
}
throw new IllegalStateException();
}
task running
f1 result: java.util.concurrent.CompletionException: java.lang.RuntimeException: timestamp: 1768455576415
f2 result: java.util.concurrent.CompletionException: java.lang.RuntimeException: timestamp: 1768455576415
e1 == e2: true
e1.cause == e2.cause: true
f1 state: FAILED
f2 state: FAILED
task running 同样只打印了一次,说明任务逻辑不会被重复执行。
e1 == e2: true 和 e1.cause == e2.cause: true 说明新老 CompletableFuture 共享返回的异常对象。
新老 CompletableFuture 状态都是 FAILED。
minimalCompletionStage
java
public CompletionStage<T> minimalCompletionStage()
将接口从 CompletableFuture 转换成了 CompletionStage,无法调用 CompletableFuture 的特有方法了。返回的 CompletionStage 的行为与上述 copy() 方法描述的相同。
返回的 CompletionStage 实际是 java.util.concurrent.CompletableFuture.MinimalStage 的实例,对 CompletableFuture 的特有方法都直接抛出了 UnsupportedOperationException 异常。
将 minimalCompletionStage() 的返回值强制转换为 CompletableFuture 调用相关方法,直接抛出 UnsupportedOperationException 异常
java
static void main() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.completedFuture("ok");
CompletionStage<String> stage = future.minimalCompletionStage();
((CompletableFuture<String>) stage).get();
}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.concurrent.CompletableFuture$MinimalStage.get(CompletableFuture.java:2973)
at com.zbs.jdk.MinimalCompletionStageTest.main(MinimalCompletionStageTest.java:19)
调用 toCompletableFuture() 方法可返回新的包含所有方法的完整 CompletableFuture。
java
static void main() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.completedFuture("ok");
CompletionStage<String> stage = future.minimalCompletionStage();
IO.println(stage.toCompletableFuture().get());
}
ok
completeAsync
java
public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier);
public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier,
Executor executor);
complete() 方法的异步版本,若 CompletableFuture 还未完成,则以 supplier 的结果完成它。
测试未完成的情况
java
static void main() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
IO.println("task1 start");
Utils.sleep(2);
IO.println("task1 complete");
return "r1";
});
future.completeAsync(() -> {
IO.println("task2 start");
Utils.sleep(1);
IO.println("task2 complete");
return "r2";
});
IO.println(future.get());
Utils.sleep(3);
}
由于 future sleep 2s,completeAsync 的任务执行时 future 还未完成,所以最终的值为 r2。
java
task1 start
task2 start
task2 complete
r2
task1 complete
如果 supplier 抛出异常,future 同样会以异常完成。
java
static void main() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
IO.println("task1 start");
Utils.sleep(1);
IO.println("task1 complete");
return "r1";
});
future.completeAsync(() -> {
throw new RuntimeException("error");
});
IO.println(future.get());
Utils.sleep(3);
}
task1 start
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException: error
at java.base/java.util.concurrent.CompletableFuture.wrapInExecutionException(CompletableFuture.java:345)
at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:440)
at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2094)
at com.zbs.jdk.CompleteAsyncTest.main(CompleteAsyncTest.java:46)
Caused by: java.lang.RuntimeException: error
at com.zbs.jdk.CompleteAsyncTest.lambda$main$1(CompleteAsyncTest.java:43)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1789)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1781)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)
测试已完成的情况
如果在调用 completeAsync(supplier) 方法时,future 已经完成了,则 supplier 逻辑不会执行。
java
static void main() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
IO.println("task1 start");
IO.println("task1 complete");
return "r1";
});
IO.println(future.get());
future.completeAsync(() -> {
IO.println("task2 start");
Utils.sleep(1);
IO.println("task2 complete");
return "r2";
});
IO.println(future.get());
Utils.sleep(3);
}
task1 start
task1 complete
r1
r1
如果在调用 completeAsync(supplier) 方法时,future 还未完成了,则 supplier 逻辑会执行。但当 supplier 执行结束时 future 已经完成了则不会对已有的结果 r1 进行修改。
java
static void main() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
IO.println("task1 start");
Utils.sleep(1);
IO.println("task1 complete");
return "r1";
});
future.completeAsync(() -> {
IO.println("task2 start");
Utils.sleep(2);
IO.println("task2 complete");
return "r2";
});
IO.println(future.get());
Utils.sleep(3);
}
task1 start
task2 start
task1 complete
r1
task2 complete
orTimeout、completeOnTimeout
java
public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit);
public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)
orTimeout: 若 CompletableFuture 在超时时间内未完成的话,则以抛出 TimeoutException 异常的方式完成。
completeOnTimeout: 若 CompletableFuture 在超时时间内未完成的话,则以 value 值完成。
orTimeout 未完成
抛出 TimeoutException
java
static void test1() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
Utils.sleep(2);
return "ok";
});
future.orTimeout(1, TimeUnit.SECONDS);
IO.println(future.get());
}
Exception in thread "main" java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutException
at java.base/java.util.concurrent.CompletableFuture.wrapInExecutionException(CompletableFuture.java:345)
at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:440)
at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2094)
at com.zbs.jdk.TimeoutTest.test1(TimeoutTest.java:28)
at com.zbs.jdk.TimeoutTest.main(TimeoutTest.java:16)
Caused by: java.util.concurrent.TimeoutException
at java.base/java.util.concurrent.CompletableFuture$Timeout.run(CompletableFuture.java:2828)
at java.base/java.util.concurrent.DelayScheduler$ScheduledForkJoinTask.compute(DelayScheduler.java:510)
at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(ForkJoinTask.java:1659)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
at java.base/java.util.concurrent.DelayScheduler.loop(DelayScheduler.java:325)
at java.base/java.util.concurrent.DelayScheduler.run(DelayScheduler.java:221)
orTimeout 已完成
无影响
java
static void test2() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
Utils.sleep(1);
return "ok";
});
future.orTimeout(2, TimeUnit.SECONDS);
IO.println(future.get());
}
ok
completeOnTimeout 未完成
以新的结果 timeout 完成
java
static void test1() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
Utils.sleep(2);
return "ok";
});
future.completeOnTimeout("timeout", 1, TimeUnit.SECONDS);
IO.println(future.get());
}
timeout
completeOnTimeout 已完成
以原结果 ok 完成
java
static void test2() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
Utils.sleep(1);
return "ok";
});
future.completeOnTimeout("timeout", 2, TimeUnit.SECONDS);
IO.println(future.get());
}
ok
static delayedExecutor
java
public static Executor delayedExecutor(long delay, TimeUnit unit);
public static Executor delayedExecutor(long delay, TimeUnit unit, Executor executor);
返回一个新的延迟执行器,该延迟执行器在给定的延迟后向给定的执行者 executor(未指定则默认为 ASYNC_POOL)提交任务。
延迟 2s 的
java
static void main() {
ExecutorService executor = Executors.newCachedThreadPool();
Executor delayedExecutor = CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, executor);
IO.println(LocalDateTime.now());
delayedExecutor.execute(() -> IO.println(LocalDateTime.now()));
Utils.sleep(3);
}
2026-01-16T14:11:15.548298700
2026-01-16T14:11:17.550877600
错误用法
==不能使用 executor.shutdown();executor.awaitTermination(3, TimeUnit.SECONDS); 等待所有任务执行完成。==因为执行 delayedExecutor.execute() 时任务并没有直接提交到 executor 中,而是提交到了中转的 ASYNC_POOL 中,等超时时间到了再提交到 executor 中。所以提前执行 executor.shutdown(); 后 executor 就无法接受任务了。
java
static void main() throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Executor delayedExecutor = CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, executor);
IO.println(LocalDateTime.now());
delayedExecutor.execute(() -> IO.println(LocalDateTime.now()));
executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);
}
2026-01-16T14:26:54.112797900
delayedExecutor 作为 CompletableFuture 的执行器
delayedExecutor 和普通的 Executor 一样,也可以作为 CompletableFuture 的执行器。
java
static void main() throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Executor delayedExecutor = CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, executor);
IO.println(LocalDateTime.now());
CompletableFuture<LocalDateTime> future = CompletableFuture.supplyAsync(
LocalDateTime::now, delayedExecutor);
IO.println(future.get());
}
2026-01-16T14:44:19.951428500
2026-01-16T14:44:21.953452400
static completedStage、failedFuture、failedStage
java
// jdk8 已存在
public static <U> CompletableFuture<U> completedFuture(U value);
public static <U> CompletableFuture<U> failedFuture(Throwable ex);
completedFuture: 返回一个已经以指定的 value 正常完成的 CompletableFuture。
failedFuture: 返回一个已经以指定的 ex 异常完成的 CompletableFuture。
java
public static <U> CompletionStage<U> completedStage(U value);
public static <U> CompletionStage<U> failedStage(Throwable ex);
同上,与 minimalCompletionStage 类似,返回的是 CompletionStage 类型。
CompletableFuture jdk12
exceptionallyAsync
java
// jdk8 已存在
public CompletableFuture<T> exceptionally(
Function<Throwable, ? extends T> fn);
public CompletableFuture<T> exceptionallyAsync(
Function<Throwable, ? extends T> fn);
public CompletableFuture<T> exceptionallyAsync(
Function<Throwable, ? extends T> fn, Executor executor);
-
当前一个阶段抛出异常时才会执行本阶段,并将抛出的异常作为参数传入;
-
若前一个阶段正常完成则不执行 fn 逻辑且返回值和前一个阶段的相同。
类似 Stream.map()。
注意: Function fn 返回值类型必须和前一阶段的一致,都是 T。
传入 fn 的异常可能是 CompletionException 类型,要获取原异常需要调用 e.getCause()。
前一个阶段报错的情况
java
static void test1() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("stage 1 error");
});
CompletableFuture<String> future2 = future1.exceptionallyAsync(e -> {
IO.println("The previous stage exception:" + e);
Throwable cause = e;
if (e instanceof CompletionException) {
cause = e.getCause();
}
IO.println("The previous stage exception cause:" + cause);
return "exceptionally stage";
});
IO.println(future2.get());
}
The previous stage exception:java.util.concurrent.CompletionException: java.lang.RuntimeException: stage 1 error
The previous stage exception cause:java.lang.RuntimeException: stage 1 error
exceptionally stage
前一个阶段未报错的情况
java
static void test2() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "stage 1 ok");
CompletableFuture<String> future2 = future1.exceptionallyAsync(e -> {
IO.println("The previous stage exception:" + e);
Throwable cause = e;
if (e instanceof CompletionException) {
cause = e.getCause();
}
IO.println("The previous stage exception cause:" + cause);
return "exceptionally stage";
});
IO.println(future2.get());
}
stage 1 ok
exceptionallyCompose、exceptionallyComposeAsync
与 exceptionallyAsync 类似只是 Function fn 的返回值从 T 变成了 CompletionStage<T>。
-
当前一个阶段抛出异常时才会执行本阶段,并将抛出的异常作为参数传入;
-
若前一个阶段正常完成则不执行 fn 逻辑且返回值和前一个阶段的相同。
类似 Stream.flatMap()。
注意: Function fn 的返回的 CompletionStage 的泛型必须和前一阶段的返回值类型一致,都是 T。
java
public CompletableFuture<T> exceptionallyCompose(
Function<Throwable, ? extends CompletionStage<T>> fn);
public CompletableFuture<T> exceptionallyComposeAsync(
Function<Throwable, ? extends CompletionStage<T>> fn);
public CompletableFuture<T> exceptionallyComposeAsync(
Function<Throwable, ? extends CompletionStage<T>> fn,
Executor executor);
适用于要返回的值需要从另一个 CompletableFuture 获取的情况,如下的示例:
前一个阶段报错的情况
java
static void test1() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("task error");
});
CompletableFuture<String> future2 = future1.exceptionallyComposeAsync(e -> {
IO.println("The previous stage exception:" + e);
Throwable cause = e;
if (e instanceof CompletionException) {
cause = e.getCause();
}
IO.println("The previous stage exception cause:" + cause);
return retryTask();
});
IO.println(future2.get());
}
static CompletableFuture<String> retryTask() {
return CompletableFuture.supplyAsync(() -> {
IO.println("retrying task");
return "retry task result";
});
}
The previous stage exception:java.util.concurrent.CompletionException: java.lang.RuntimeException: task error
The previous stage exception cause:java.lang.RuntimeException: task error
retrying task
retry task result
前一个阶段未报错的情况
java
static void test2() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "task ok");
CompletableFuture<String> future2 = future1.exceptionallyComposeAsync(e -> {
IO.println("The previous stage exception:" + e);
Throwable cause = e;
if (e instanceof CompletionException) {
cause = e.getCause();
}
IO.println("The previous stage exception cause:" + cause);
return retryTask();
});
IO.println(future2.get());
}
task ok