【并发编程】Java8 - CompletableFuture,增强版Future
1. 简介
CompletableFuture是Java8的新特性,在Future基础上,增加流式计算、函数式编程、完成通知、自定义异常、多个Future组合处理等能力,使得在多线程协同处理时更加顺利。
2. 相关博客
【并发编程】Java5 - Future,基本使用
【并发编程】Java5 - CompletionService,将异步执行与获取结果分离
【并发编程】Guava - ListenableFuture,避免Future获取阻塞问题,增加回调
3. CompletableFuture应用
3.1 supplyAsync/runAsync
supplyAsync和runAsync都可以创建CompletableFuture实例,并异步执行提交的任务。区别在于:supplyAsync带有返回值,runAsync无返回值。
- 创建带有返回值的异步任务
/**
* 创建带有返回值的异步任务
*/
@Test
public void testSupplyAsync() throws ExecutionException, InterruptedException {
CompletableFuture<Boolean> completableFuture = CompletableFuture.supplyAsync(() -> {
log.info("任务执行中...");
return Boolean.TRUE;
});
Boolean result = completableFuture.get();
log.info("执行结果:" + result);
}
控制台输出:
19:56:10.381 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务执行中...
19:56:10.393 [main] INFO com.c3stones.test.CompletableFutureTest - 执行结果:true
- 创建带有返回值的异步任务,并指定线程池
/**
* 创建带有返回值的异步任务,并指定线程池
*/
@Test
public void testSupplyAsync2() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
CompletableFuture<Boolean> completableFuture = CompletableFuture.supplyAsync(() -> {
log.info("任务执行中...");
return Boolean.TRUE;
}, executorService);
Boolean result = completableFuture.get();
log.info("执行结果:" + result);
}
控制台输出:
19:57:32.507 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务执行中...
19:57:32.513 [main] INFO com.c3stones.test.CompletableFutureTest - 执行结果:true
不指定线程池默认使用ForkJoinPool.commonPool()。
- 创建无返回值的异步任务
/**
* 创建无返回值的异步任务
*/
@Test
public void testRunAsync() throws ExecutionException, InterruptedException {
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
log.info("任务执行中...");
});
Void result = completableFuture.get();
log.info("执行结果:" + result);
}
控制台输出:
19:59:29.721 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务执行中...
19:59:29.729 [main] INFO com.c3stones.test.CompletableFutureTest - 执行结果:null
- 创建无返回值的异步任务,并指定线程池
/**
* 创建无返回值的异步任务,并指定线程池
*/
@Test
public void testRunAsync2() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
log.info("任务执行中...");
}, executorService);
Void result = completableFuture.get();
log.info("执行结果:" + result);
}
控制台输出:
20:00:06.732 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务执行中...
20:00:06.740 [main] INFO com.c3stones.test.CompletableFutureTest - 执行结果:null
3.2 流式连接函数
3.2.1 thenApply/thenApplyAsync
thenApply和thenApplyAsync都是任务执行完成后的回调函数,并将任务的返回结果作为入参,并带有返回值。区别在于:thenApply执行回调函数和任务使用的是同一线程,而thenApplyAsync会使用不同的线程,并且thenApplyAsync支持指定线程池。
- thenApply
/**
* 任务1执行完返回结果<br/>
* 回调函数入参为任务1的返回结果,并带有返回值
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testThenApply() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = completableFuture1.thenApply((result) -> {
log.info("回调函数执行中...");
return result * 10;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:08:40.723 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:08:40.730 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
20:08:40.731 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:08:40.731 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:100
- thenApplyAsync
/**
* 任务1执行完返回结果<br/>
* 回调函数入参为任务1的返回结果,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenApplyAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = completableFuture1.thenApplyAsync((result) -> {
log.info("回调函数执行中...");
return result * 10;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:10:30.067 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:10:30.074 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:10:30.075 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
20:10:30.075 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:100
3.2.2 thenAccept/thenAcceptAsync
thenAccept和thenAcceptAsync都是任务执行完成后的回调函数,并将任务的返回结果作为入参,但无返回值。区别在于:thenAccept执行回调函数和任务使用的是同一线程,而thenAcceptAsync会使用不同的线程,并且thenAcceptAsync支持指定线程池。
- thenAccept
/**
* 任务1执行完返回结果<br/>
* 回调函数入参为任务1的返回结果,无返回值
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testThenAccept() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Void> completableFuture2 = completableFuture1.thenAccept((result) -> {
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:13:22.635 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:13:22.641 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:13:22.641 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
20:13:22.642 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
- thenAcceptAsync
/**
* 任务1执行完返回结果<br/>
* 回调函数入参为任务1的返回结果,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenAcceptAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Void> completableFuture2 = completableFuture1.thenAcceptAsync((result) -> {
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:14:24.234 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:14:24.240 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:14:24.303 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
20:14:24.304 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
3.2.3 thenRun/thenRunAsync
thenRun和thenRunAsync都是任务执行完成后的回调函数,但无入参,也无返回值。区别在于:thenRun执行回调函数和任务使用的是同一线程,而thenRunAsync会使用不同的线程,并且thenRunAsync支持指定线程池。
- thenRun
/**
* 任务1执行完返回结果<br/>
* 回调函数无入参,无返回值
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testThenRun() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Void> completableFuture2 = completableFuture1.thenRun(() -> {
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:17:37.329 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:17:37.335 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
20:17:37.335 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:17:37.335 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
- thenRunAsync
/**
* 任务1执行完返回结果<br/>
* 回调函数无入参,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenRunAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Void> completableFuture2 = completableFuture1.thenRunAsync(() -> {
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:18:39.630 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:18:39.638 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:18:39.656 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
20:18:39.656 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
3.2.4 whenComplete/whenCompleteAsync
whenComplete和whenCompleteAsync都是任务执行完成后的回调函数,带有两个参数,参数1为任务指定的返回结果,参数2为任务2执行时抛出的异常。调用get方法获取任务的执行结果时,如果任务执行正常,则正常返回结果,如果执行异常,则抛出异常。区别在于:whenComplete执行回调函数和任务使用的是同一线程,而whenCompleteAsync会使用不同的线程,并且whenCompleteAsync支持指定线程池。
- whenComplete
/**
* 任务1执行成功<br/>
* 回调函数入参1为任务1的返回结果,入参2为null
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testWhenComplete() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = completableFuture1.whenComplete((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:24:25.589 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:24:25.597 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:24:25.597 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:24:25.598 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:10
/**
* 任务1执行抛出异常<br/>
* 回调函数入参1为null.入参2为任务1抛出的异常
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testWhenCompleteException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
int a = 1 / 0;
return 10;
});
CompletableFuture<Integer> completableFuture2 = completableFuture1.whenComplete((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:25:34.521 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:25:34.529 [ForkJoinPool.commonPool-worker-1] ERROR com.c3stones.test.CompletableFutureTest - 任务 1 返回异常:java.lang.ArithmeticException: / by zero
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testWhenCompleteException(CompletableFutureTest.java:263)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testWhenCompleteException$18(CompletableFutureTest.java:251)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- whenCompleteAsync
/**
* 任务1执行完返回结果<br/>
* 回调函数入参1为null.入参2为任务1抛出的异常
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testWhenCompleteAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = completableFuture1.whenCompleteAsync((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:37:29.881 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:37:29.886 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:37:29.887 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:37:29.887 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:10
/**
* 任务1执行抛出异常<br/>
* 回调函数入参1为null.入参2为任务1抛出的异常
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testWhenCompleteAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
int a = 1 / 0;
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = completableFuture1.whenCompleteAsync((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:39:00.814 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:39:00.821 [pool-1-thread-2] ERROR com.c3stones.test.CompletableFutureTest - 任务 1 返回异常:java.lang.ArithmeticException: / by zero
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testWhenCompleteAsyncException(CompletableFutureTest.java:320)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testWhenCompleteAsyncException$22(CompletableFutureTest.java:308)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.2.5 handle/handleAsync
handle和handleAsync都是任务执行完成后的回调函数,带有两个参数,参数1为任务指定的返回结果,参数2为任务2执行时抛出的异常,并且带有返回值。调用get方法获取任务的执行结果时,如果任务执行正常,则正常返回结果,如果执行异常,则抛出异常。区别在于:handle执行回调函数和任务使用的是同一线程,而handleAsync会使用不同的线程,并且handleAsync支持指定线程池。和whenComplete和whenCompleteAsync区别为:当发生异常时,whenComplete和whenCompleteAsync不会吞掉异常,即最终结果还是会抛出异常;而handle和handleAsync可以将异常进行替换,即最终结果可以是替换异常后的其他正常结果。
- handle
/**
* 任务1执行完返回结果<br/>
* 回调函数入参1为任务1的返回结果,入参2为null,并带有返回值
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testHandle() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = completableFuture1.handle((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
return result * 10;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:43:18.876 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:43:18.881 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:43:18.881 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:43:18.881 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:100
/**
* 任务1执行抛出异常<br/>
* 回调函数入参1为任务1的返回结果,入参2为null,并带有返回值
* <p>
* 相同线程执行
* </p>
*/
@Test
public void testHandleException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
int a = 1 / 0;
return 10;
});
CompletableFuture<Integer> completableFuture2 = completableFuture1.handle((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
return result * 10;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:45:24.873 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:45:24.888 [main] ERROR com.c3stones.test.CompletableFutureTest - 任务 1 返回异常:java.lang.ArithmeticException: / by zero
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testHandleException(CompletableFutureTest.java:375)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testHandleException$26(CompletableFutureTest.java:362)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- handleAsync
/**
* 任务1执行完返回结果<br/>
* 回调函数入参1为任务1的返回结果,入参2为null,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testHandleAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = completableFuture1.handleAsync((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
return result * 10;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:46:43.338 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:46:43.345 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:46:43.347 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
20:46:43.347 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:100
/**
* 任务1执行抛出异常<br/>
* 回调函数入参1为任务1的返回结果,入参2为null,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testHandleAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
int a = 1 / 0;
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = completableFuture1.handleAsync((result, exception) -> {
if (exception != null) {
log.error("任务 1 返回异常:" + exception.getMessage());
} else {
log.info("任务 1 返回结果:" + result);
}
return result * 10;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("回调函数返回结果:" + completableFuture2.get());
}
控制台输出:
20:47:22.106 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
20:47:22.113 [pool-1-thread-2] ERROR com.c3stones.test.CompletableFutureTest - 任务 1 返回异常:java.lang.ArithmeticException: / by zero
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testHandleAsyncException(CompletableFutureTest.java:434)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testHandleAsyncException$30(CompletableFutureTest.java:421)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3 多任务组合
3.3.1 thenCombine/thenCombineAsync
thenCombine和thenCombineAsync都是将两个异步任务组合后处理。当两个任务都执行完成后,执行回调函数。回调函数会将两个任务的返回结果作为入参,并带有返回值。如果两个任务有一个执行异常,则抛出异常。区别在于:thenCombine执行回调函数时会公用执行两个任务的其中一个的线程,而thenCombineAsync会使用不同的线程,并且thenCombineAsync支持指定线程池。
- thenCombine
/**
* 任务1和任务2都执行成功,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,并带有返回值
* <p>
* 回调函数公用两个任务其中一个线程执行
* </p>
*/
@Test
public void testThenCombine() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
return 20;
});
CompletableFuture<Integer> completableFuture3 = completableFuture1.thenCombine(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
return result1 + result2;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:15:55.676 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:15:55.676 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:15:55.684 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:15:55.684 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到 任务 1 结果:10,获取到任务 2 结果:20
21:15:55.684 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
21:15:55.684 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
21:15:55.684 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:30
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,并带有返回值
* <p>
* 回调函数公用两个任务其中一个线程执行
* </p>
*/
@Test
public void testThenCombineException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
int a = 1 / 0;
return 20;
});
CompletableFuture<Integer> completableFuture3 = completableFuture1.thenCombine(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
return result1 + result2;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:17:24.832 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:17:24.832 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:17:24.839 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testThenCombineException(CompletableFutureTest.java:495)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testThenCombineException$36(CompletableFutureTest.java:484)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- thenCombineAsync
/**
* 任务1和任务2都执行成功,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenCombineAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
return 20;
}, executorService);
CompletableFuture<Integer> completableFuture3 = completableFuture1.thenCombineAsync(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
return result1 + result2;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:19:29.638 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:19:29.636 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:19:29.642 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:19:29.642 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
21:19:29.645 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到 任务 1 结果:10,获取到任务 2 结果:20
21:19:29.645 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
21:19:29.645 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:30
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenCombineAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
int a = 1 / 0;
return 20;
}, executorService);
CompletableFuture<Integer> completableFuture3 = completableFuture1.thenCombineAsync(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
return result1 + result2;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:23:26.457 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:23:26.463 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:23:26.467 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testThenCombineAsyncException(CompletableFutureTest.java:560)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testThenCombineAsyncException$42(CompletableFutureTest.java:549)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3.2 thenAcceptBoth/thenAcceptBothAsync
thenAcceptBoth和thenAcceptBothAsync都是将两个异步任务组合后处理。当两个任务都执行完成后,执行回调函数。回调函数会将两个任务的返回结果作为入参,但无返回值。如果两个任务有一个执行异常,则抛出异常。区别在于:thenAcceptBoth执行回调函数时会公用执行两个任务的其中一个的线程,而thenAcceptBothAsync会使用不同的线程,并且thenAcceptBothAsync支持指定线程池。
- thenAcceptBoth
/**
* 任务1和任务2都执行成功,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,无返回值
* <p>
* 回调函数公用两个任务其中一个线程执行
* </p>
*/
@Test
public void testThenAcceptBoth() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.thenAcceptBoth(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:31:14.624 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:31:14.624 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:31:14.630 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:31:14.630 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到 任务 1 结果:10,获取到任务 2 结果:20
21:31:14.630 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
21:31:14.630 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
21:31:14.630 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,无返回值
* <p>
* 回调函数公用两个任务其中一个线程执行
* </p>
*/
@Test
public void testThenAcceptBothException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
int a = 1 / 0;
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.thenAcceptBoth(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:33:23.532 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:33:23.527 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:33:23.539 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testThenAcceptBothException(CompletableFutureTest.java:619)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testThenAcceptBothException$48(CompletableFutureTest.java:609)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- thenAcceptBothAsync
/**
* 任务1和任务2都执行成功,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenAcceptBothAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.thenAcceptBothAsync(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:34:44.099 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:34:44.099 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:34:44.105 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:34:44.106 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
21:34:44.106 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到 任务 1 结果:10,获取到任务 2 结果:20
21:34:44.106 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
21:34:44.106 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为任务1和任务2的返回结果,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testThenAcceptBothAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
int a = 1 / 0;
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.thenAcceptBothAsync(completableFuture2, (result1, result2) -> {
log.info("回调函数获取到 任务 1 结果:" + result1 + ",获取到任务 2 结果:" + result2);
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:35:31.832 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:35:31.833 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:35:31.839 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testThenAcceptBothAsyncException(CompletableFutureTest.java:682)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testThenAcceptBothAsyncException$54(CompletableFutureTest.java:672)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3.3 runAfterBoth/runAfterBothAsync
runAfterBoth和runAfterBothAsync都是将两个异步任务组合后处理。当两个任务都执行完成后,执行回调函数。回调函数无入参,也无返回值。如果两个任务有一个执行异常,则抛出异常。区别在于:runAfterBoth执行回调函数时会公用执行两个任务的其中一个的线程,而runAfterBothAsync会使用不同的线程,并且runAfterBothAsync支持指定线程池。
- runAfterBoth
/**
* 任务1和任务2都执行成功,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 回调函数公用两个任务其中一个线程执行
* </p>
*/
@Test
public void testRunAfterBoth() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterBoth(completableFuture2, () -> {
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:39:33.677 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:39:33.683 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:39:33.684 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:39:33.684 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
21:39:33.684 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
21:39:33.684 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 回调函数公用两个任务其中一个线程执行
* </p>
*/
@Test
public void testRunAfterBothException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
int a = 1 / 0;
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterBoth(completableFuture2, () -> {
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:40:44.127 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:40:44.128 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:40:44.136 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testRunAfterBothException(CompletableFutureTest.java:739)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testRunAfterBothException$60(CompletableFutureTest.java:730)
at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- runAfterBothAsync
/**
* 任务1和任务2都执行成功,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testRunAfterBothAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterBothAsync(completableFuture2, () -> {
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:42:19.533 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:42:19.533 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:42:19.539 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
21:42:19.540 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
21:42:19.546 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
21:42:19.546 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testRunAfterBothAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
int a = 1 / 0;
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterBothAsync(completableFuture2, () -> {
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
21:43:36.457 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
21:43:36.464 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
21:43:36.464 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testRunAfterBothAsyncException(CompletableFutureTest.java:800)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testRunAfterBothAsyncException$66(CompletableFutureTest.java:791)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3.4 applyToEither/applyToEitherAsync
applyToEither和applyToEitherAsync都是将两个异步任务组合后处理。回调函数会将第一个完成的任务的返回结果作为入参,并带有返回值。如果两个任务有一个执行异常,则抛出异常。区别在于:applyToEither执行回调函数时会公用第一个完成的任务的线程,而applyToEitherAsync会使用不同的线程,并且applyToEitherAsync支持指定线程池。
- applyToEither
/**
* 任务1或任务2执行成功,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,并带有返回值
* <p>
* 回调函数和第一个完成的任务使用相同线程执行
* </p>
*/
@Test
public void testApplyToEither() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
});
CompletableFuture<Integer> completableFuture3 = completableFuture1.applyToEither(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
return result * 10;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:08:52.369 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:08:52.371 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:08:53.376 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:08:53.376 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:08:53.376 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:08:54.378 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:08:54.379 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:100
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,并带有返回值
* <p>
* 回调函数和第一个完成的任务使用相同线程执行
* </p>
*/
@Test
public void testApplyToEitherException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
});
CompletableFuture<Integer> completableFuture3 = completableFuture1.applyToEither(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
return result * 10;
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:11:25.616 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:11:25.616 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:11:26.621 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:11:26.621 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:11:26.621 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testApplyToEitherException(CompletableFutureTest.java:881)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testApplyToEitherException$72(CompletableFutureTest.java:870)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- applyToEitherAsync
/**
* 任务1或任务2执行成功,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testApplyToEitherAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
}, executorService);
CompletableFuture<Integer> completableFuture3 = completableFuture1.applyToEitherAsync(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
return result * 10;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:12:08.089 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:12:08.089 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:12:09.096 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:12:09.096 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:12:09.096 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:12:10.096 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:12:10.096 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:100
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,并带有返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testApplyToEitherAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
}, executorService);
CompletableFuture<Integer> completableFuture3 = completableFuture1.applyToEitherAsync(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
return result * 10;
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:12:40.922 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:12:40.928 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:12:41.928 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:12:41.929 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:12:41.929 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testApplyToEitherAsyncException(CompletableFutureTest.java:966)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testApplyToEitherAsyncException$78(CompletableFutureTest.java:955)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3.5 acceptEither/acceptEitherAsync
acceptEither和acceptEitherAsync都是将两个异步任务组合后处理。回调函数会将第一个完成的任务的返回结果作为入参,但无返回值。如果两个任务有一个执行异常,则抛出异常。区别在于:acceptEither执行回调函数时会公用第一个完成的任务的线程,而acceptEitherAsync会使用不同的线程,并且acceptEitherAsync支持指定线程池。
- acceptEither
/**
* 任务1或任务2执行成功,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,无返回值
* <p>
* 回调函数和第一个完成的任务使用相同线程执行
* </p>
*/
@Test
public void testAcceptEither() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.acceptEither(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:15:07.135 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:15:07.135 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:15:08.141 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:15:08.141 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:15:08.141 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:15:09.141 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:15:09.141 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,无返回值
* <p>
* 回调函数和第一个完成的任务使用相同线程执行
* </p>
*/
@Test
public void testAcceptEitherException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.acceptEither(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:18:56.628 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:18:56.628 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:18:57.633 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:18:57.633 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:18:57.633 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testAcceptEitherException(CompletableFutureTest.java:1045)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testAcceptEitherException$84(CompletableFutureTest.java:1035)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- acceptEitherAsync
/**
* 任务1或任务2执行成功,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testAcceptEitherAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.acceptEitherAsync(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:21:27.580 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:21:27.636 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:21:28.601 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:21:28.602 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:21:28.602 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:21:29.637 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:21:29.637 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数入参为第一个完成的任务的返回结果,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testAcceptEitherAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.acceptEitherAsync(completableFuture2, (result) -> {
log.info("回调函数获取到结果:" + result);
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:22:25.767 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:22:25.764 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:22:26.772 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:22:26.772 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数获取到结果:10
22:22:26.772 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testAcceptEitherAsyncException(CompletableFutureTest.java:1128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testAcceptEitherAsyncException$90(CompletableFutureTest.java:1118)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3.6 runAfterEither/runAfterEitherAsync
runAfterEither和runAfterEitherAsync都是将两个异步任务组合后处理。回调函数无入参,也无返回值。如果两个任务有一个执行异常,则抛出异常。区别在于:runAfterEither执行回调函数时会公用第一个完成的任务的线程,而runAfterEitherAsync会使用不同的线程,并且runAfterEitherAsync支持指定线程池。
- runAfterEither
/**
* 任务1或任务2执行成功,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 回调函数和第一个完成的任务使用相同线程执行
* </p>
*/
@Test
public void testRunAfterEither() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterEither(completableFuture2, () -> {
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:25:15.172 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:25:15.252 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:25:16.183 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:25:16.183 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:25:17.253 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:25:17.253 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 回调函数和第一个完成的任务使用相同线程执行
* </p>
*/
@Test
public void testRunAfterEitherException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
});
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterEither(completableFuture2, () -> {
log.info("回调函数执行中...");
});
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:25:46.913 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:25:46.913 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:25:47.920 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:25:47.920 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testRunAfterEitherException(CompletableFutureTest.java:1205)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testRunAfterEitherException$96(CompletableFutureTest.java:1196)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
- runAfterEitherAsync
/**
* 任务1或任务2执行成功,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testRunAfterEitherAsync() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterEitherAsync(completableFuture2, () -> {
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:26:24.311 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:26:24.311 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:26:25.318 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:26:25.318 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
22:26:26.318 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:26:26.318 [main] INFO com.c3stones.test.CompletableFutureTest - 回调函数返回结果:null
/**
* 任务1执行成功,任务2执行失败,再执行回调函数<br/>
* 回调函数无入参,无返回值
* <p>
* 提交给线程池,不同线程执行
* </p>
*/
@Test
public void testRunAfterEitherAsyncException() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}, executorService);
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
}, executorService);
CompletableFuture<Void> completableFuture3 = completableFuture1.runAfterEitherAsync(completableFuture2, () -> {
log.info("回调函数执行中...");
}, executorService);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("回调函数返回结果:" + completableFuture3.get());
}
控制台输出:
22:27:06.844 [pool-1-thread-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:27:06.844 [pool-1-thread-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:27:07.850 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:27:07.850 [pool-1-thread-3] INFO com.c3stones.test.CompletableFutureTest - 回调函数执行中...
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testRunAfterEitherAsyncException(CompletableFutureTest.java:1286)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testRunAfterEitherAsyncException$102(CompletableFutureTest.java:1277)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
3.3.7 allOf
allOf将多个任务组合后处理,当所有任务都执行成功后,返回null,只要有一个任务执行异常,则抛出异常。
- 任务1、任务2、任务3都执行成功
/**
* 任务1、任务2、任务3都执行成功,返回null
*/
@Test
public void testAllOf() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
});
CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(() -> {
log.info("任务 3 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 30;
});
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(completableFuture1, completableFuture2, completableFuture3);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("任务 3 返回结果:" + completableFuture3.get());
log.info("全部任务返回结果:" + completableFuture.get());
}
控制台输出:
22:32:05.089 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:32:05.089 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:32:05.091 [ForkJoinPool.commonPool-worker-4] INFO com.c3stones.test.CompletableFutureTest - 任务 3 执行中...
22:32:06.095 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:32:07.096 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:32:08.095 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 3 返回结果:30
22:32:08.095 [main] INFO com.c3stones.test.CompletableFutureTest - 全部任务返回结果:null
- 任务1、任务3执行成功,任务2执行异常
/**
* 任务1、任务3执行成功,任务2执行异常
*/
@Test
public void testAllOfException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
});
CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(() -> {
log.info("任务 3 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 30;
});
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(completableFuture1, completableFuture2, completableFuture3);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("任务 3 返回结果:" + completableFuture3.get());
log.info("全部任务返回结果:" + completableFuture.get());
}
控制台输出:
22:34:03.486 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:34:03.486 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:34:03.486 [ForkJoinPool.commonPool-worker-3] INFO com.c3stones.test.CompletableFutureTest - 任务 3 执行中...
22:34:04.499 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testAllOfException(CompletableFutureTest.java:1372)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testAllOfException$108(CompletableFutureTest.java:1355)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
3.3.8 anyOf
anyOf将多个任务组合后处理,只要有一个任务执行成功,返回该任务结果,只要有一个任务执行异常,则抛出异常。
- 任务1、任务2、任务3只要有一个任务执行成功,返回该任务结果
/**
* 任务1、任务2、任务3只要有一个任务执行成功,返回该任务结果
*/
@Test
public void testAnyOf() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 20;
});
CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(() -> {
log.info("任务 3 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 30;
});
CompletableFuture<Object> completableFuture = CompletableFuture.anyOf(completableFuture1, completableFuture2, completableFuture3);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("任务 3 返回结果:" + completableFuture3.get());
log.info("全部任务返回结果:" + completableFuture.get());
}
控制台输出:
22:36:10.596 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:36:10.632 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:36:10.633 [ForkJoinPool.commonPool-worker-3] INFO com.c3stones.test.CompletableFutureTest - 任务 3 执行中...
22:36:11.605 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
22:36:12.632 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 2 返回结果:20
22:36:13.634 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 3 返回结果:30
22:36:13.634 [main] INFO com.c3stones.test.CompletableFutureTest - 全部任务返回结果:10
- 任务1、任务3执行成功,任务2执行异常
/**
* 任务1、任务3执行成功,任务2执行异常
*/
@Test
public void testAnyOfException() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
log.info("任务 2 执行中...");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 20;
});
CompletableFuture<Integer> completableFuture3 = CompletableFuture.supplyAsync(() -> {
log.info("任务 3 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 30;
});
CompletableFuture<Object> completableFuture = CompletableFuture.anyOf(completableFuture1, completableFuture2, completableFuture3);
log.info("任务 1 返回结果:" + completableFuture1.get());
log.info("任务 2 返回结果:" + completableFuture2.get());
log.info("任务 3 返回结果:" + completableFuture3.get());
log.info("全部任务返回结果:" + completableFuture.get());
}
控制台输出:
22:36:44.307 [ForkJoinPool.commonPool-worker-2] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
22:36:44.307 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 2 执行中...
22:36:44.315 [ForkJoinPool.commonPool-worker-4] INFO com.c3stones.test.CompletableFutureTest - 任务 3 执行中...
22:36:45.316 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.c3stones.test.CompletableFutureTest.testAnyOfException(CompletableFutureTest.java:1459)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testAnyOfException$114(CompletableFutureTest.java:1442)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
3.4 获取结果
方法名称及参数 | 描述 |
---|---|
T get() throws InterruptedException, ExecutionException | 获取结果 |
T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException | 获取结果,超时自动退出 |
T getNow(T valueIfAbsent) | 获取结果,未完成则返回传入的预期值 |
T join() | 获取结果,和get()一样。区别在于:get()会抛出异常,join()不会抛出异常,出现异常时抛出未经检查( CompletionException)异常 |
boolean complete(T value) | 设置任务完成,完成后所有阻塞方法获取到结果。如果未完成,则返回传入的预期值,一般非执行任务的线程调用 |
boolean completeExceptionally(Throwable ex) | 设置任务完成,完成后所有阻塞方法获取到结果。如果未完成,则抛出传入的异常,一般非执行任务的线程调 |
- get()
/**
* 测试获取结果
*/
@Test
public void testGet() {
// 记录开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
try {
log.info("任务 1 返回结果:" + completableFuture1.get());
} catch (InterruptedException e) {
log.error("中断异常");
} catch (ExecutionException e) {
log.error("执行异常");
}
stopWatch.stop();
log.info("总耗时:" + stopWatch.getTotalTimeMillis() + " ms");
}
控制台输出:
23:17:53.410 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
23:17:56.417 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:10
23:17:56.419 [main] INFO com.c3stones.test.CompletableFutureTest - 总耗时:3020 ms
- get(long timeout, TimeUnit unit)
/**
* 测试获取结果,超时自动退出
*/
@Test
public void testGetTimeout() {
// 记录开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
try {
log.info("任务 1 返回结果:" + completableFuture1.get(2, TimeUnit.SECONDS));
} catch (InterruptedException e) {
log.error("中断异常");
} catch (ExecutionException e) {
log.error("执行异常");
} catch (TimeoutException e) {
log.error("超时异常");
}
stopWatch.stop();
log.info("总耗时:" + stopWatch.getTotalTimeMillis() + " ms");
}
控制台输出:
23:20:44.971 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
23:20:46.968 [main] ERROR com.c3stones.test.CompletableFutureTest - 超时异常
23:20:46.969 [main] INFO com.c3stones.test.CompletableFutureTest - 总耗时:2009 ms
- getNow(T valueIfAbsent)
/**
* 测试获取结果,未完成返回期预期
*/
@Test
public void testGetNow() {
// 记录开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
});
log.info("任务 1 返回结果:" + completableFuture1.getNow(-1));
stopWatch.stop();
log.info("总耗时:" + stopWatch.getTotalTimeMillis() + " ms");
}
控制台输出:
23:21:13.897 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
23:21:13.897 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:-1
23:21:13.906 [main] INFO com.c3stones.test.CompletableFutureTest - 总耗时:20 ms
- join()
/**
* 测试获取结果,不会抛出异常
*/
@Test
public void testJoin() {
// 记录开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 10;
});
log.info("任务 1 返回结果:" + completableFuture1.join());
stopWatch.stop();
log.info("总耗时:" + stopWatch.getTotalTimeMillis() + " ms");
}
控制台输出:
23:23:08.238 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1592)
at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.ArithmeticException: / by zero
at com.c3stones.test.CompletableFutureTest.lambda$testJoin$119(CompletableFutureTest.java:1570)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
... 5 more
- complete(T value)
/**
* 测试通知任务完成,未完成返回预期值
*/
@Test
public void testComplete() {
// 记录开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 10;
});
new Thread(() -> {
completableFuture1.complete(-2);
}, "其他线程").start();
try {
log.info("任务 1 返回结果:" + completableFuture1.get());
} catch (InterruptedException e) {
log.error("中断异常");
} catch (ExecutionException e) {
log.error("执行异常");
}
stopWatch.stop();
log.info("总耗时:" + stopWatch.getTotalTimeMillis() + " ms");
}
控制台输出:
23:23:55.594 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
23:23:55.594 [main] INFO com.c3stones.test.CompletableFutureTest - 任务 1 返回结果:-2
23:23:55.601 [main] INFO com.c3stones.test.CompletableFutureTest - 总耗时:17 ms
- completeExceptionally(Throwable ex)
/**
* 测试通知任务完成,未完成返回预期异常
*/
@Test
public void testCompleteExceptionally() {
// 记录开始时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
log.info("任务 1 执行中...");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
int a = 1 / 0;
return 10;
});
new Thread(() -> {
completableFuture1.completeExceptionally(new RuntimeException("提前完成异常"));
}, "其他线程").start();
try {
log.info("任务 1 返回结果:" + completableFuture1.get());
} catch (InterruptedException e) {
log.error("中断异常");
} catch (ExecutionException e) {
if (e.getCause() instanceof RuntimeException) {
log.error("预期异常:{}", e.getCause().getMessage());
} else {
log.error("非预期异常");
}
}
stopWatch.stop();
log.info("总耗时:" + stopWatch.getTotalTimeMillis() + " ms");
}
控制台输出:
23:24:16.676 [ForkJoinPool.commonPool-worker-1] INFO com.c3stones.test.CompletableFutureTest - 任务 1 执行中...
23:24:16.676 [main] ERROR com.c3stones.test.CompletableFutureTest - 预期异常:提前完成异常
23:24:16.685 [main] INFO com.c3stones.test.CompletableFutureTest - 总耗时:21 ms