звоню ExecutorService.shutDown () в java

Я начинаю изучать класс ExecutorService. Документация (и учебные пособия в интернете) говорят, чтобы всегда вызывать ExecutorService.shutDown () для восстановления ресурсов. однако в документации также говорится, что после вызова shutDown () новые задачи не будут приняты. Итак, мой вопрос: всегда ли мне нужно создавать экземпляр нового ExecutorService, когда мне нужно распараллелить обработку данных?

прямо сейчас у меня есть список вызываемых объектов, и я делаю следующий.

public void someMethod() {
 List<OuterCallable> outerCallables = getOuterCallables();
 ExecutorService executor = Executor.newFixedThreadPool(NUM_CPUS);
 executor.invokeAll(tasks);
 executor.shutDown();
}

однако мой OuterCallable также разделяет данные или выполняет обработку данных параллельно с помощью InnerCallable.

public class OuterCallable implements Callable<Long> {
 public Long call() throws Exception {
  long result = 0L;

  List<InnerCallable> innerCallables = getInnerCallables();
  ExecutorServices executor = Executor.newFixedThreadPool(NUM_CPUS);
  executor.invokeAll(tasks);
  executor.shutDown();

  return result;
 }
}    

Я не могу вспомнить, было ли это для ExecutorService или подхода Fork/Join, но я помню документы и учебники, говорящие, что фактическая параллельная процедура для управления данными не должна включать операции ввода-вывода, и все должно быть сделано в памяти. однако, в моем InnerCallable, я фактически делаю вызовы JDBC (не показанный ниже.)

в конечном счете, то, как я использую ExecutorService, работает, но у меня все еще есть проблемы.

  1. мой подход выше хорошей практики программирования с помощью ExecutorService?
  2. должен ли я использовать одноэлементный экземпляр ExecutorService?
  3. должен ли я не только избегать операций ввода-вывода внутри моих параллельных методов, но и вызовов JDBC?

в качестве последней проблемы я пытался немного исследовать бит на Fork / Join vs ExecutorService. я наткнулся на статью, которая полностью взорвала API/классы Fork/Join. стоит ли изучать Fork / Join? я видел несколько статей о stackoverflow и в других местах, где тесты используются для сравнения Fork/Join vs ExecutorService, и есть графики, показывающие лучшее использование процессора Fork/Join vs ExecutorService (через Диспетчер задач Windows). однако, когда я использую ExecutorService (JDK 1.7.x), мое использование процессора макс. есть ExecutorService с С JDK?

любая помощь/руководство будет оценен.

1 ответов


вы должны добавить awaitTermination звонит, потому что shutDown возвращает, не дожидаясь завершения вызова. Кроме этого,

  1. вы OuterCallableс последовательными зависимостями? Если это так, ваш подход прекрасен, но использование ForkJoinPool было бы предпочтительнее, потому что он будет держать количество рабочих потоков низким. Если нет, то было бы лучше представить большую сплющенную коллекцию Callables до одного Executor.
  2. только если вы хотите использовать ExecutorService в несколько различные процедуры и хотите, чтобы избежать передачи его вокруг. Если он используется только в someMethod, можно также создать его там, как вы это делаете.
  3. вы должны избегать процедур ввода-вывода, которые потребуют много времени для завершения. Если ваш ExecutorService имеет 4 рабочих потока, и все они блокируются при вводе-выводе, JVM вообще не будет использовать CPU, даже если другие вызываемые объекты могут ожидать выполнения работы с процессором. Несколько вызовов JDBC в порядке, пока запросы не занимают много времени полный.