CompletableFuture.exceptionally() method需要一个lambda,但是没有任何方法可以使用自定义的Executor,甚至是" ... Async"它的味道。
哪个执行者特别执行lambda运行?它是否是运行原始CompletableFuture的同一执行者抛出异常?或者(如果是这种情况我会感到惊讶)是commonPool吗?
答案 0 :(得分:5)
表单JDK错误讨论CompletableFuture.exceptionally may execute on main thread:
CompletableFuture.exceptionally
不接受Executor参数 因为它不是为执行特殊任务而设计的 异步。如果尚未完成依赖任务,则执行异常任务 将在依赖任务完成的同一线程上完成。
如果完成了从属任务,那么特殊任务就会完成 完成对异常执行调用的线程。
这与任何非异步行为都会发生相同的行为 执行,例如thenAccept。
保证在线程上执行异常任务 在执行程序线程池中,然后有必要使用 whenCompleteAsync 或 handleAsync 并传入执行程序。
答案 1 :(得分:0)
我做了一些实验。看起来没有确定性地选择特殊处理程序的执行程序。
以下是实验代码:
heap_sizeof()
节目输出:有时是
ForkJoinPool ex = new ForkJoinPool(2,
ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, false);
// AsyncThreadLocal.requestId.set((int)(Math.random()*1000));
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
throw new RuntimeException();
// return 3;
}, ex);
CompletableFuture<Integer> f8 = f1.exceptionally(t -> {
System.out.println(Thread.currentThread().getName());
return 5;
});
Thread.sleep(10000);
其他时间是
ForkJoinPool-1-worker-1
main
答案 2 :(得分:0)
看起来它与 CompletionStage
在同一个执行器中运行 public static void main(String[] args) throws Exception {
//ExecutorService executorService = Executors.newFixedThreadPool(3);
ExecutorService executorService = Executors.newWorkStealingPool();
while (true) {
int i = Instant.now().getNano();
CompletableFuture<?> completableFuture = CompletableFuture.supplyAsync(
()-> {
System.err.printf("async thread at %d -> %s\n", i, Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
throw new RuntimeException();
}, executorService);
completableFuture.exceptionally(
(err)-> {
System.err.printf("error thread for %d -> %s\n", i, Thread.currentThread().getName());
return null;
});
TimeUnit.SECONDS.sleep(5);
}
}
对于固定尺寸:
异步线程418000000 - &gt;池-1-线程1
错误线程418000000 - &gt;池-1-线程1
646000000的异步线程 - &gt;池-1-线程2
错误线程为646000000 - &gt;池-1-线程2
646000000的异步线程 - &gt;池-1-线程3
错误线程为646000000 - &gt;池-1-线程3
646000000的异步线程 - &gt;池-1-线程1
错误线程为646000000 - &gt;池-1-线程1
647000000的异步线程 - &gt;池-1-线程2
错误线程为647000000 - &gt;池-1-线程2
用于窃取池(4核):
96000000的异步线程 - &gt; ForkJoinPool -1-工人-1
96000000的错误帖子 - &gt; ForkJoinPool -1-工人-1
196000000的异步线程 - &gt; ForkJoinPool -1-工人-1
错误线程为196000000 - &gt; ForkJoinPool -1-工人-1
异步线程在197000000 - &gt; ForkJoinPool -1-工人-1
错误线程为197000000 - &gt; ForkJoinPool -1-工人-1
异步线程在197000000 - &gt; ForkJoinPool -1-工人-1
错误线程为197000000 - &gt; ForkJoinPool -1-工人-1
异步线程在197000000 - &gt; ForkJoinPool -1-工人-1
错误线程为197000000 - &gt; ForkJoinPool -1-工人-1
异步线程在197000000 - &gt; ForkJoinPool -1-工人-1
没有遗嘱执行人:
848000000的异步线程 - &gt; ForkJoinPool.commonPool工人-1
错误线程为848000000 - &gt; ForkJoinPool.commonPool工人-1
async thread at 944000000 - &gt; ForkJoinPool.commonPool工人-1
944000000的错误线程 - &gt; ForkJoinPool.commonPool工人-1
async thread at 944000000 - &gt; ForkJoinPool.commonPool工人-1
944000000的错误线程 - &gt; ForkJoinPool.commonPool工人-1
async thread at 944000000 - &gt; ForkJoinPool.commonPool工人-1
944000000的错误线程 - &gt; ForkJoinPool.commonPool工人-1
async thread at 944000000 - &gt; ForkJoinPool.commonPool工人-1
944000000的错误线程 - &gt; ForkJoinPool.commonPool工人-1
答案 3 :(得分:0)
请注意,从JDK 12开始,有CompletionStage.exceptionallyAsync
(还有exceptionallyAsync
需要一个Executor
)。