У меня есть набор записей для обработки, и обработка может быть распараллелена, поэтому я создал ExecutorService (через Исполнители # newCachedThreadPool ()). Обработка отдельной записи сама по себе состоит из параллелизируемых шагов, поэтому я хотел бы использовать другой ExecutorService. Есть ли простой способ заставить этот новый пул использовать тот же базовый пул потоков? Это вообще желательно? Спасибо.




Можете ли вы просто передать ссылку на существующий ExecutorService своим рабочим объектам?
public class Task implements Runnable {
private final ExecutorService threadPool;
private final SubTask[] subtasks;
public Task(ExecutorService threadPool) {
this.threadPool = threadPool;
this.subtasks = createSubtasksIGuess();
}
public void run() {
for(SubTask sub : subtasks)
threadPool.submit(sub);
}
}
Чтобы ответить на ваш вопрос: нет, два объекта ExecutorServiceне могу совместно используют пул потоков. Однако вы можете совместно использовать ExecutorService между своими объектами или, в качестве альтернативы, создать несколько исполнителей, если это необходимо, хотя это менее рекомендуется.
Лучшее решение: поделитесь Executor между своими объектами.
Краткий ответ: Нет.
Более длинный ответ: для этого вам понадобится собственная реализация. ExecutorService - это интерфейс, и AbstractExecutorService довольно легко реализовать.
Если вы хотите, чтобы два ExecutorService совместно использовали один пул ThreadPool (например, с разным максимальным значением активного потока), вы можете использовать шаблон прокси, чтобы ThreadPool совместно использовал ExecutorService.
(В моем случае мне нужно было дождаться завершения всех задач для каждого Executor. То есть использовать методы shutdown () / awaitTermination ())
Для этого есть несколько веских причин, например отдельные границы и метрики для каждой очереди. AFAIK, Cassandra 2.1 немало выиграла от использования реализации службы исполнителя с общим пулом потоков; код находится в https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/concurrent/SEPExecutor.java.
Конечно, исходная проблема требует прямого использования API-интерфейсов задач fork / join, которые доступны в Java 7.
Другой вариант использования, который у меня был недавно, - это иметь пул с одним потоком с одной очередью, но с двумя исполнителями, один из которых использует AbortPolicy, а другой CallerRunsPolicy.
Спасибо! Здесь был бы красивый образец прокси. Дублирование кода Дуга Ли для подключаемого пула потоков было бы слишком подвержено ошибкам.