ExecutorService ждет завершения всего Future

У меня есть код для ExecutorService.

try{
    ExecutorService executor = Executors.newFixedThreadPool(5);
    List<Callable<String>> taskList = new ArrayList<Callable<String>>(5);
    for(int i=1;i<=5;i++){
        taskList.add(new SimpleTask());
    }

    List<Future<String>> list =  executor.invokeAll(taskList);
    executor.shutdown();
    System.out.println(list.get(0).get());
    System.out.println("Exit");
}catch(Exception e){
    e.printStackTrace();
}

class SimpleTask implements Callable<String> {
    @Override
    public String call() throws Exception {     
        return new Date().toString();
    }
}

Я хочу знать, что list.get(0).get() будет ждать завершения всех задач?

Нет, он будет ждать завершения только одного Future (первого)

Scary Wombat 12.04.2018 08:38

Как сказал вомбат, нет. Итак, вы спрашиваете, как это сделать, или это отвечает на ваш вопрос?

daniu 12.04.2018 08:40

Я поставил точку останова в call () и пропускаю первую задачу. Затем также ждем завершения всех задач.

mcacorner 12.04.2018 08:41

Если вы установите точку останова в call(), вам придется пропустить ее пять раз, потому что именно так часто она будет вызываться. Похоже на то, почему он ждет.

daniu 12.04.2018 08:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
4
4 928
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Нет, код в том виде, как он есть, не будет ждать завершения каждой задачи. Вызывая list.get(0).get(), вы получаете самый первый дополнительный вызов get() на нем, который блокирует поток в соответствии с документация.

Чтобы дождаться завершения каждого вызываемого объекта, вам нужно перебрать список и посмотреть, все ли выполнено. Конечно, вы можете сделать это, вызывая get() на каждом из них, но тогда вы все время блокируете свой основной поток. Я сам предпочитаю иметь возможность делать что-то, пока я жду выполнения других потоков.

Пример использования потоков Java 8:

// filter if any future is not done yet
while ( list.stream().anyMatch(i->!i.isDone()) )
{
  // Do whatever you want parallel to the evaluation of the Future objects

  // example
  System.err.println( "Not all are done yet." );
}
// process your results

// example:
String[] results = list.stream().map( Main::evalGet ).toArray(String[]::new);

Примечание. priavte static <T> TevalGet(Future<T> fu) - это просто функция-оболочка, которая сохраняет лямбда-выражение в чистоте от обработки исключений и выглядит примерно так:

private static <T> T evalGet( Future<T> fu )
  {
    T obj = null;
    try
    {
      obj = fu.get();
    }
    catch ( InterruptedException | ExecutionException e )
    {
      e.printStackTrace();
    }
    return obj;
  }

См .: stackoverflow.com/questions/34440604/…

mcacorner 12.04.2018 10:28
Ответ принят как подходящий

Здесь код будет ждать не выполнения оператора list.get(0).get(), а оператора executor.invokeAll(taskList), потому что сам метод invokeAll() будет ожидать усложнения всех потоков.

Чтобы узнать больше Отвечать

Другие вопросы по теме