捕获ExecutorService中所有Futures / Callables的异常

时间:2017-03-06 04:44:06

标签: java multithreading

我有一个ExecutorService,其中包含许多正在运行的Callables。我有Futures这些Callables的列表。如果Callables中的一个投出Exception,我想尽快找出答案。所有Callables同样可能会抛出ExceptionCallables通常会运行几个小时。

通常的方法似乎是使用Future.get()方法。但是,您只能将其用于FutureFuture。如果另一个Exception抛出Future.isDone(),我就不会收到通知。所以我在考虑编写一个循环来检查所有Futures的 public class Session { public long Id { get; set; } public string SessionId { get; set; } public string Status { get; set; } } 方法,并在每次迭代后休眠一段时间。但是,这种方法并不是很好,所以我想知道是否有更好的方法呢?

2 个答案:

答案 0 :(得分:2)

您应该使用ExecutorCompletionService,将执行者包装在其中,然后调用#take()将返回第一个完成的结果。

示例:

CompletionService<Object> completionService = new ExecutorCompletionService<>(executor);
//submit a bunch of tasks
IntStream.range(0, 100).forEach(i-> completionService.submit(Object::new));
//Wait for any of them to complete, wrap in a loop to take them all
completionService.take();

答案 1 :(得分:2)

您可以将CompletableFuture用作用例

static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
  

返回一个新的CompletableFuture,它在任何一个时完成   给定CompletableFutures完成,结果相同。否则,如果   它完成异常,返回的CompletableFuture也是如此   因此,使用CompletionException将此异常作为其原因。   如果未提供CompletableFutures,则返回不完整   CompletableFuture。

您应该将所有期货存储在列表中。 `

现在

List<CompletableFuture<?>> futureList = // all futures;
while(futureList.size()>0){
    CompletableFuture<?> completed = CompletableFuture.anyOf(futureList); //convert futureList to array
    if(completed.isCompletedExceptionally()){
       // first future that completed with an exception
    }else{
       //future completed without exception, store the result or process
       futureList.remove(completed); // remove it from the incomplete list
    }
}

您可能会获得CompletableFuture之类的

final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
         //...long running...
         return "returnVal";
      },
   executor); //here executor is your executor pool

如果您不想使用显式执行程序池

    final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
             //...long running...
             return "returnVal";
          });

但是,在这种情况下,它将提交给ForkJoinPool。commonPool()