我有一个ExecutorService
,其中包含许多正在运行的Callables
。我有Futures
这些Callables
的列表。如果Callables
中的一个投出Exception
,我想尽快找出答案。所有Callables
同样可能会抛出Exception
。 Callables
通常会运行几个小时。
通常的方法似乎是使用Future.get()
方法。但是,您只能将其用于Future
个Future
。如果另一个Exception
抛出Future.isDone()
,我就不会收到通知。所以我在考虑编写一个循环来检查所有Futures的 public class Session
{
public long Id { get; set; }
public string SessionId { get; set; }
public string Status { get; set; }
}
方法,并在每次迭代后休眠一段时间。但是,这种方法并不是很好,所以我想知道是否有更好的方法呢?
答案 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()