ExecutorCompletionService
(带有记住提交任务的回调的线程池)看起来像一个傻瓜:
CompletionService<Response> executorService =
new ExecutorCompletionService<>(Executors.newFixedThreadPool(10));
int totalExternal = 0;
for(Item item : items){
if(item is external){
executorService.submit(externalCall(item));
++totalExternal;
}
if(item is internal){
populate response object and add to list
}
}
for (int i = 0; i < totalExternal; ++totalExternal) {
addAsynchResultToResponseList(executorService.take().get());
}
为清楚起见externalCall(item)
,定义如下:
Callable<Response> externalCall(Item item) {
return new Callable<Response>() {
//...
}
}
显然,一旦你异步,结果列表可以有任意顺序。
另一种方法是使用普通ExecutorService
的并有一个中间的List<Future<Response>>
. 诀窍是使用AsyncResult
包装器来包装内部响应(它创建Future
立即完成并返回传递的值)。
List<Future<Response>> futures = new ArrayList<>();
for(Item item : items){
if(item is external){
futures.add(executorService.submit(externalCall(item)));
}
if(item is internal){
futures.add(new AsyncResult(synchResponse));
}
}
现在您可以简单地迭代futures
. AsyncResult
将立即返回,因为该值在创建时已经是计算机 ( synchResponse
)。但是您将不得不等待Future
从线程池返回的 s 。
请记住,这Future.get()
允许您检索原始异常。此外,Future
列表中 s 的顺序与原始项目的顺序相同,因此如果第 n 个Future
失败,则items
列表中的第 n 个项目是原因。