java - 并发 - foreach 循环中的非阻塞设计

标签 java multithreading concurrency future

我正在开发一项返回 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 是程序化的和阻塞的,我想要的是一个非阻塞设计,这样,如果该项目是外部的,则触发调用并继续列表中的下一个项目。然后当循环完成时,我可以等待所有完成。

执行此操作的好方法是什么?我也在考虑为每个职责创建单独的类。

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

最佳答案

ExecutorCompletionService (带有记住提交任务的回调的线程池)看起来像一个 git 错误:

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 项列表是原因。

关于java - 并发 - foreach 循环中的非阻塞设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13500670/

相关文章:

python - 为什么concurrent.futures的submit()不立即将控制权返回给主程序?

java - ReentrantLock 不起作用

Java ExecutorService invokeAll() 中断

java - 我在使用 sleep 时遇到问题?

c++ - 使用 lambda 作为试运行选项正常吗?

java - 我们可以配置 simple-xml 让它忽略未知节点吗

java - JVM 如何知道何时抛出 NullPointerException

java - 如何在我的 Netbeans 项目中包含外部 jar

java - 使用我的类而不是 JAR 中的类

java - JIT 是这种行为的原因吗?