【问题标题】:how can executorService store result of task `i` in `array[i]`?executorService 如何在 `array[i]` 中存储任务`i`的结果?
【发布时间】:2015-03-29 11:53:25
【问题描述】:

我在post 读到了关于executorService 的文章

当订单很重要时,我想填充固定大小的结果集合。

当我知道任务i 应该将其结果存储在array[i] 中时,我可以填充一个数组。

是否有另一种内置方式按任务提交的顺序存储结果?我可以填写一个列表而不是一个数组吗?

【问题讨论】:

  • 你有n个任务,你需要并行执行来计算每个任务的结果,但需要和任务顺序相同的结果?

标签: java arrays multithreading list concurrency


【解决方案1】:

您可以使用Executors.invokeAll() 方法。来自 javadocs:

参数:

tasks - 任务的集合

返回:

代表任务的 Futures 列表,与给定任务列表的迭代器生成的顺序相同,每个任务都已完成。

ExecutorService executor = Executors.newFixedThreadPool(SOME_SIZE);

Collection<Callable<T>> tasks = ...; // fill collection with callable tasks

List<Future<T>> futures = executor.invokeAll(tasks);

invokeAll() 在所有提交的任务执行完毕后返回。

然后遍历返回的期货并在每个期货上调用get()

List<T> results = 
    futures.stream().map(Future::get).collect(Collectors.toList());

结果的顺序将匹配tasks 集合之一。

单行:

List<T> results = 
    executor.invokeAll(tasks).stream().map(Future::get).collect(Collectors.toList());

【讨论】:

    【解决方案2】:

    只需将submit() 返回的Futures 存储在一个数组或列表中,然后遍历此列表并在每个未来调用get()

    List<Callable<Result>> tasks = ...;
    List<Future<Result>> futures = new ArrayList<>();
    for (Callable<Result> task : tasks) {
        futures.add(executor.submit(task));
    }
    
    List<Result> results = new ArrayList<>();
    for (Future<Result> future : futures) {
        results.add(future.get());
    }
    

    【讨论】:

      【解决方案3】:

      Future 对象的结果添加到列表中,其顺序与创建时相同:

      // given some tasks and an executor 
      List<Callable<MyResult>> tasks;
      ExecutorService exec;
      
      List<MyResult> results = exec.invokeAll(tasks).stream()
        .map(Future::get).collect(Collectors.toList());
      

      【讨论】:

      • 这会同时执行吗?我的理解是一个流只迭代一次,结合所有的流操作。这将在提交后立即调用 Future.get,从而导致串行执行。
      • @meriton 这将调用 Future/get() 串行,但这并不意味着任务不会并行执行。只是他们的结果是连续收集的。它基本上是我回答中代码的 Java8 版本。
      • @meriton Collection 的stream() 方法返回一个顺序 流,而parallelStream() 方法返回一个并行:我的代码将保持秩序。
      • 我担心的不是 Future.get 是按顺序调用的。我担心在提交剩余任务之前调用 Future.get,因为流会折叠所有地图操作。也就是说,如果我们执行Arrays.asList(1,2,3).stream().map(print("S")).map(print("G")).collect(Collectors.toList());,我们会得到输出SGSGSG,而不是并行执行所需的SSSGGG
      • @JBNizet 对。那么,该编辑会修复它吗?有没有更好的方法——现在看起来有点傻。
      猜你喜欢
      • 2011-05-05
      • 2017-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 2021-03-10
      • 2012-09-07
      • 2012-10-20
      相关资源
      最近更新 更多