Разница между Executor и ExecutorCompletionservice в Java - PullRequest
15 голосов
/ 13 октября 2011

Поскольку само название вопроса говорит о том, в чем разница между классами Executors и ExecutorCompletionService в java?

Я новичок в Threading, поэтому, если кто-нибудь сможет объяснить с помощью фрагмента кода, это поможетмного.

Ответы [ 2 ]

20 голосов
/ 14 октября 2011

Предположим, у вас есть набор задач A, B, C, D, E, и вы хотите выполнить каждую из них асинхронно в Executor и обработать результаты 1 на 1 по мере их завершения.

При Executor,Вы должны сделать это так:

List<Future<?>> futures = new ArrayList<Future<?>>();
futures.add(executorService.submit(A));
futures.add(executorService.submit(B));
futures.add(executorService.submit(C));
futures.add(executorService.submit(D));
futures.add(executorService.submit(E));

//This loop must process the tasks in the order they were submitted: A, B, C, D, E
for (Future<?> future:futures) {
    ? result = future.get();
    // Some processing here
}

Проблема этого метода в том, что нет гарантии, что задача A будет выполнена первой.Таким образом, возможно, что основной поток будет блокировать в ожидании завершения задачи A, когда он может обрабатывать результат другой задачи (скажем, задача B).Задержка обработки результатов может быть уменьшена с помощью ExecutorCompletionService.

List<Future<?>> futures = new ArrayList<Future<?>>();
futures.add(executorCompletionService.submit(A));
futures.add(executorCompletionService.submit(B));
futures.add(executorCompletionService.submit(C));
futures.add(executorCompletionService.submit(D));
futures.add(executorCompletionService.submit(E));

//This for loop will process the tasks in the order they are completed,  
//regardless of submission order
for (int i=0; i<futures.size(); i++) {
    ? result = executorCompletionService.take().get();
    // Some processing here
}

Так что, по сути, ExecutorCompletionService можно использовать, чтобы выжать немного больше эффективности, когда порядок выполнения задач обработки не имеет значения.

Однако следует отметить одну важную вещь.Реализация ExecutorCompletionService содержит очередь результатов.Если take или poll не вызваны для опустошения этой очереди, произойдет утечка памяти.Некоторые люди используют Future, возвращаемый submit для обработки результатов, и это НЕ правильное использование.

3 голосов
/ 13 октября 2011

ExecutorCompletionService просто перенесет и делегирует к нормальному Executor и предложит удобные методы для получения самых последних выполненных задач.

API имеет несколько примеров, которые должны помочь вам

http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html

...