2

我正在开发一个返回List<Response>对象的服务。

有两种对象可以构建响应。其中一个从内部数据中填充内容,另一个伸出服务并获取数据。

for(Item item : items){
   if(item is external){
     call service and get result and populate Response and add to List
   }

   if(item is internal)
   {
     populate response object and add to list
   }
}

当前的 impl 是程序性的和阻塞的,我想要的是一个非阻塞设计,这样,如果项目是外部的,则触发调用并继续列表中的下一个项目。然后当循环完成时,我可以等待所有完成。

什么是这样做的好方法?我也在考虑为每个职责创建单独的类。

编辑:引入的原因是减少延迟命中。

4

3 回答 3

5

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 个项目是原因。

于 2012-11-21T19:38:29.880 回答
1

我要做的是将所有操作包装在Callables 中,将它们提交给 s,将ExecutorService返回Future的 s 存储在列表中。

然后当他们都完成后,在主线程中填充结果列表。

于 2012-11-21T19:32:00.770 回答
0

当项目在外部时,为了让事情继续进行,操作call service应该启动某种异步活动(例如,aThreadRunnable提交到某种Executor)。这个活动应该有一个回调机制,以便get result完成后,它可以执行任务的最后一部分:populate Response and add to List

您必须同步访问List或将所有访问安排为单线程。

于 2012-11-21T19:37:49.557 回答