2013-07-02 2 views
6

У меня есть набор Futures, созданный путем отправки Callable s на номер Executor. Псевдокод:Тайм-аут в ожидании завершения партии фьючерсов?

for all tasks 
    futures.add(executor.submit(new callable(task))) 

Теперь я хотел бы получить все фьючерсы, ожидающие не более n секунд, пока все не закончится. Я знаю, что могу позвонить Future#get(timeout), но если я назову это последовательно для всех своих фьючерсов в цикле, таймауты начнут складываться. Псевдо код:

for all futures 
    future.get(timeout) 

get блоки с тайм-аут, пока результат будет готов. Поэтому, если первое завершено непосредственно перед таймаутом, а второе также завершается непосредственно перед таймаутом, и так все время выполнения составляет number of futures * timeout максимум, а не timeout.

Следовательно, я ищу метод, который принимает список Future s и тайм-аут, выполняет все параллельно и затем возвращает коллекцию будущих результатов. Есть идеи?

+0

Это еще не совсем ясно. Что вы хотите выполнить с задачами, которые не были выполнены, когда истекает время ожидания? Вы хотите, чтобы их отменили или разрешили продолжить? –

+0

Их следует отменить. Кроме того, почему-то мне нужно знать, какие из них были выполнены, а какие нет. Думаю, для этого я мог повторить еще раз по фьючерсам и вызывать 'isDone' на всех из них. –

ответ

5

Вы можете использовать ExecutorService.invokeAll:

Выполнение поставленных задач, возвращая список фьючерсов, имеющих свой статус и результаты, когда все полные или тайм-аут истекает, в зависимости от того произойдет первым. Future.isDone() верно для каждого элемента возвращаемого списка. По возвращении задачи, которые не были выполнены, отменены. Обратите внимание, что завершенная задача может завершиться либо нормально, либо путем исключения исключения. Результаты этого метода не определены, если данный сборник изменен во время выполнения этой операции.


Если у вас уже есть Future сек, что вам нужно контролировать и не могут использовать invokeAll, вы можете просто измерить тайм-аут себя. Псевдо код:

long endTime = System.currentTimeMillis() + timeoutMS; 
for(f : futures) 
    f.get(Math.max(0, endTime - System.currentTimeMillis()), TimeUnit.MILLISECONDS); 

Таким образом, вы даете каждому будущее самое длительность, что осталось, пока не достигнете тайм-аут.

+0

'ExecutorService.invokeAll' звучит так, как я после, спасибо. Для всех фьючерсов, которые не были завершены во времени 'isCancelled == true', правильно (так я интерпретирую Javadoc)? Как я узнаю, что «будущее» завершилось исключением? «Обратите внимание, что завершенная задача могла завершиться либо нормально, либо путем исключения исключения» - это сложно ... –

+1

@ MarcelStör Да, фьючерсы, которые не были завершены, отменены ('isCancelled() == true'). Затем вы определяете, что произошло с «Будущим», когда вы вызываете его ['get()'] (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html# get% 28% 29) (после возврата 'invokeAll'). Если 'get' throws' CancellationException', вы знаете, что он был отменен. Если он выбрасывает «ExecutionException», это означает, что «Будущее» выполнено с исключением, а исключение доступно через «ExecutionException.getCause()». –

Смежные вопросы