CompletableFuture.exceptionally with executor

时间:2016-07-07 19:58:37

标签: asynchronous nonblocking completable-future

CompletableFuture.exceptionally() method需要一个lambda,但是没有任何方法可以使用自定义的Executor,甚至是" ... Async"它的味道。

哪个执行者特别执行lambda运行?它是否是运行原始CompletableFuture的同一执行者抛出异常?或者(如果是这种情况我会感到惊讶)是commonPool吗?

4 个答案:

答案 0 :(得分:5)

表单JDK错误讨论CompletableFuture.exceptionally may execute on main thread

  

CompletableFuture.exceptionally不接受Executor参数   因为它不是为执行特殊任务而设计的   异步。

     

如果尚未完成依赖任务,则执行异常任务   将在依赖任务完成的同一线程上完成。

     

如果完成了从属任务,那么特殊任务就会完成   完成对异常执行调用的线程。

     

这与任何非异步行为都会发生相同的行为   执行,例如thenAccept。

     

保证在线程上执行异常任务   在执行程序线程池中,然后有必要使用    whenCompleteAsync handleAsync 并传入执行程序。

答案 1 :(得分:0)

我做了一些实验。看起来没有确定性地选择特殊处理程序的执行程序。

  1. 如果我没有放置任何断点,则异常处理程序偶尔会在与具有异常处理程序的CompletableFuture相同的执行程序中执行。此外,我可以注意到它在相同的 ForkJoinTask中运行。一旦进入两次或三次运行,就会在主线程上执行。
  2. 如果我在附加异常处理程序之前在运行时放置了断点并在那里等了一会儿,那么在主(调用)线程上始终执行异常lambda!
  3. 以下是实验代码:

    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)。