[英]Catching Exceptions of all Futures/Callables in an ExecutorService
I have an ExecutorService
containing a number of running Callables
. 我有一个
ExecutorService
其中包含许多正在运行的Callables
。 I have a list of Futures
for these Callables
. 我有这些
Callables
的Futures
清单。 I want to find out as soon as possible if one of the Callables
throws an Exception
. 我想尽快找出其中一个
Callables
抛出Exception
。 All Callables
are equally likely to throw an Exception
. 所有
Callables
都有可能抛出Exception
。 The Callables
usually run for several hours. Callables
通常运行几个小时。
The usual approach seems to be to use the Future.get()
method. 通常的方法似乎是使用
Future.get()
方法。 However, you can only use this for one Future
. 但是,您只能将此用于一个
Future
。 If another Future
throws an Exception
I am not notified. 如果另一个
Future
引发Exception
不会通知我。 So I was thinking of writing a loop that checks the Future.isDone()
method for all Futures and sleeping for some time after each iteration. 因此,我正在考虑编写一个循环,该循环检查所有Future的
Future.isDone()
方法,并在每次迭代后休眠一段时间。 However, this approach is not really nice, so I was wondering if there is a better way of doing this? 但是,这种方法并不是很好,所以我想知道是否有更好的方法?
You should use an ExecutorCompletionService
, wrap your executor with it and then calling #take()
will return the first completed result. 您应该使用
ExecutorCompletionService
,用它包装您的执行ExecutorCompletionService
,然后调用#take()
将返回第一个完成的结果。
Example: 例:
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();
You can use CompletableFuture for your use-case 您可以在用例中使用CompletableFuture
static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
Returns a new CompletableFuture that is completed when any of the given CompletableFutures complete, with the same result.
返回一个新的CompletableFuture,它在任何给定的CompletableFutures完成时完成,并具有相同的结果。 Otherwise, if it completed exceptionally, the returned CompletableFuture also does so, with a CompletionException holding this exception as its cause.
否则,如果异常完成,则返回的CompletableFuture也会这样做,并且CompletionException将此异常作为其原因。 If no CompletableFutures are provided, returns an incomplete CompletableFuture.
如果未提供CompletableFuture,则返回不完整的CompletableFuture。
You should store all your futures in a list. 您应该将所有期货存储在列表中。 `
`
Now 现在
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
}
}
You may obtain a CompletableFuture
like 您可能会获得类似的
CompletableFuture
final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//...long running...
return "returnVal";
},
executor); //here executor is your executor pool
If you don't want to use explicit executor pool 如果您不想使用显式执行程序池
final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//...long running...
return "returnVal";
});
However, in this case it will be submitted to the ForkJoinPool .commonPool() 但是,在这种情况下,它将被提交到ForkJoinPool .commonPool()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.