簡體   English   中英

可調用對象的並行執行

[英]Parallel execution of callables

我想並行執行多個可調用對象。 但似乎 ExecutorService 總是等到所有可調用對象都完成。

我嘗試了以下方法:

final int nThreads = 10;
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
List<PrimeCallable> tasks = new ArrayList<PrimeCallable>();
for(int i = 0; i < nThreads; i++) {
    tasks.add(new PrimeCallable(0, i * 100 + 100, "thread" + i));
}

try {
    for(Future<List<Integer>> result : executorService.invokeAll(tasks)) {
        List<Integer> integers = result.get();
        for(Integer i : integers){
            System.out.println(i);
        }
    }
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ExecutionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

現在,當 executorService 中的所有可調用對象都完成時,將調用 for 循環。 據我所知,沒有 executorService.isParallel 設置器;-)。

讓可調用對象並行運行的正確方法是什么?

感謝您的提示!

invokeAll的 javadocs 說;

執行給定的任務,當全部完成時返回一個持有狀態和結果的 Futures 列表。 Future.isDone() 對於返回列表的每個元素都是 true。

因此, invokeAll會阻塞,直到集合中的每個任務都完成。

Executor 服務並行運行所有可調用對象。 它所做的只是等待所有並行任務完成后再繼續。 所以它不像所有任務都是串行運行的。

聽起來你想要的部分是延遲執行——你不想在提取結果之前復制 memory 中的結構。

我會將其視為迭代+轉換問題。 首先,在您的輸入上定義一個迭代器,這樣每次調用 next() 都會返回一個 Callable,它將在您的系列中產生下一個值。

轉換階段是對這些 Callables 應用並行或並發評估,如下所示(未測試):

public class ConcurrentTransform
{
  private final ExecutorService executor;
  private final int maxBuffer;

  public ConcurrentTransform(ExecutorService executor, int maxWorkBuffer) {
    this.executor = executor;
    this.maxBuffer = Math.max(1, maxWorkBuffer);
  }

  public <T> Iterator<T> apply(final Iterator<Callable<T>> input) {
    // track submitted work
    final BlockingQueue<Future<T>> submitted = new LinkedBlockingQueue<Future<T>>();

    // submit first N tasks
    for (int i=0; i<maxBuffer && input.hasNext(); i++) {
      Callable<T> task = input.next();
      Future<T> future = executor.submit(task);
      submitted.add(future);
    }

    return new Iterator<T>(){
      @Override
      public synchronized boolean hasNext() {
        return !submitted.isEmpty();
      }
      @Override
      public T next() {
        Future<T> result;
        synchronized (this) {
          result = submitted.poll();
          if (input.hasNext()) {
            submitted.add(executor.submit(input.next()));
          }
        }

        if (result != null) {
          try {
            return result.get(); // blocking
          } catch (Exception e) {
            if (e instanceof RuntimeException) {
               throw (RuntimeException) e;
            } else {
               throw new RuntimeException(e);
            }
          }
        } else {
          throw new NoSuchElementException();
        }
      }
      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }};
  }
}

在調用 apply(...) 之后,您將遍歷結果值,在幕后將並行執行 Callable 對象並以與輸入相同的順序返回結果。 一些改進是允許阻塞 result.get() 調用的可選超時,或者在轉換本身內管理線程池。

如果您想在結果發生時查看結果,請使用ExecutorCompletionService

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM