Java: ExecutorService с Callables: Timeout: future.get () приводит к прямому останову программы - PullRequest
2 голосов
/ 06 марта 2012

Я использую ExecutorService в Java и заметил поведение, которое я не понимаю. Я использую Callable, и когда я вызываю свои потоки (классы, которые реализуют Callable), я устанавливаю таймаут. Затем я жду результата с помощью future.get() и после того, как хочу проверить с помощью future.isDone(), произошел ли тайм-аут во время выполнения задач.

Как я читал в документации по invokeAll с таймаутом: returns a list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list. If the operation did not time out, each task will have completed. If it did time out, some of these tasks will not have completed.

Поэтому я подумал, что получу список результатов в будущем в обоих случаях, если истечет время ожидания, а если нет.

Теперь происходит следующее: когда происходит тайм-аут, код не запускается после future.get(), и я даже не дохожу до того, что могу проверить, не произошел ли тайм-аут с future.isDone(). Я не уловил никаких исключений, я непосредственно привел к блоку finally в моем коде, который я действительно не понимаю.

вот фрагмент моего кода:

     try {
        // start all Threads
        results = pool.invokeAll(threads, 3, TimeUnit.SECONDS);

        for (Future<String> future : results)
        {
            try
            {
                // this method blocks until it receives the result, unless there is a 
                // timeout set.
                final String rs = future.get();

                if (future.isDone())
                {
                    // if future.isDone() = true, a timeout did not occur. 
                   // do something
                }
                else
                {
                    // timeout
                    // log it and do something
                    break;
                }
            }
            catch (ExecutionException e)
            {
               // log messages and break, this is a snippet!
            }
            catch (InterruptedException ex)
            {
               // log message and break, this is a snippet!
            }
        }

    }
    catch (InterruptedException ex)
    {
        // log message, this is a snippet!
    }
    finally
    {
        // when a timeout occurs, the code jumps from future.get() directly to this point!
    }

Может кто-нибудь объяснить мне, почему я не могу дозвониться до future.isDone() и что я должен изменить, чтобы иметь возможность распознавать тайм-ауты?

Спасибо!

Ответы [ 3 ]

6 голосов
/ 06 марта 2012

Вы не ловите CancellationException, который, скорее всего, будет брошен после вызова get. Обратите внимание, что это исключение распространяется на RuntimeException, и компилятор не предупредит вас, чтобы его перехватить.

Чтение документов для invokeAll:

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

2 голосов
/ 06 марта 2012

Я не уверен, что вы используете invokeAll правильно.Javadoc говорит:

Выполняет заданные задачи, возвращая список Фьючерсов с их статусом и результатами, когда все завершено или истекло время ожидания, в зависимости от того, что произойдет раньше.Future.isDone () имеет значение true для каждого элемента возвращаемого списка.

Так какой смысл вызывать isDone, поскольку для всех возвращенных фьючерсов isDone - это правда?

0 голосов
/ 06 августа 2016

Использование isCancelled.Если false, это означает отсутствие тайм-аута.тогда вы можете вызвать get () и перехватить executeException, если задание не истекло, но возникло исключение по любой другой причине, например, nullpointer, assert и т. д.

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