Nano Hash - криптовалюты, майнинг, программирование

awaitDone в FutureTask выдает InterruptedException

Я искал в Интернете уже неделю, но ни один из сообщений, таких как Как мне заставить FutureTask возвращаться после TimeoutException?, кажется, отвечает на мой вопрос. Я извлек образец кода из своего кода:

 Future<Object> result = executorService.submit(new Callable<Object>() {
    @Override public Object call() throws Exception {
     ...........
    }
  });

  try {
    return result.get(timeout.getValue(), timeout.getUnit().getTimeUnit());
  } catch (TimeoutException e) {
    result.cancel(true);
    throw new TTimeoutException(e);
  }

Если я запускаю это, иногда (1 из 1000) я получаю

 java.lang.InterruptedException
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
        at java.util.concurrent.FutureTask.get(FutureTask.java:199)
        at com.abc.callers.A.call(A.java:83)

а строка №:83 — это результат.get() будущей задачи, показанной в приведенном выше примере кода.

Теперь мой вопрос: может ли вызов result.cancel(true) в будущем вызвать InterruptedException в result.get? Если нет, то кто может изменить статус прерывания моего текущего потока? AFAIK result.get() - это не тот же поток, что и тот, который выполняет мою отправленную задачу, которую я отменяю.


  • Отмена не должна вызывать InterruptedException, поскольку номер строки указывает на вызов result.get(). 27.11.2014
  • @AndyDufresne Нет, это стек вызовов из прерванного потока. Он не говорит вам, откуда произошло прерывание. 27.11.2014
  • @AndyDufresne: я бы не был так уверен в этом, поскольку исключения, возникающие в будущих потоках, направляются на вызов метода get(). Это одна из причин, по которой этот метод должен вызываться, даже если он ничего не возвращает. 27.11.2014
  • @HovercraftFullOfEels — поправьте меня, если я ошибаюсь — в приведенном выше фрагменте кода отсутствует блок catch для InterruptedException, но если предположить, что это то же самое, что и TimeOutException, как вызов метода result.cancel() может вызвать прерывание в том же потоке? 27.11.2014
  • @AndyDufresne: согласно FutureTask API, если во время выполнения FutureTask выдается InterruptedException, оно будет выброшено при вызове get(), что означает, что оно будет выброшено в потоке, вызываемом get(), который обычно не совпадает с потоком FutureTask. 27.11.2014
  • @HovercraftFullOfEels InterruptedException внутри задачи будет отображаться как ExecutionException, InterruptedException из get() означает, что (get-) вызывающий поток был прерван. ideone.com/zTL1Nq 27.11.2014
  • @zapl: да, исключение прерывания будет заключено в ExecutionException. 27.11.2014
  • Интересно.. Вы можете получить прерванное исключение, используя команду cancel(true), ideone.com/Fy4AJU - тот же код, однако, вызывает у меня CancellationException локально. Должно быть что-то изменилось в реализации get() в приоритете отмены над прерываниями?! 27.11.2014
  • Из фрагмента кода, который вы разместили, невозможно получить InterruptedException в результате cancel, поскольку вы не вызываете cancel, когда выдается InterruptedException. Или наоборот, если вы вызываете cancel в блоке catch (TimeoutException…, вы не можете получить InterruptedException в get, так как get уже завершено с TimeoutException. Очевидно, что причина InterruptedException кроется в фрагменте кода, который вы не разместили здесь. 01.12.2014

Ответы:


1

Из Javadoc:

boolean cancel(boolean mayInterruptIfRunning)

Попытки отменить выполнение этой задачи. Эта попытка не удастся, если задача уже выполнена, уже отменена или не может быть отменена по какой-либо другой причине. В случае успеха, и эта задача не запущена при вызове отмены, эта задача никогда не должна запускаться. Если задача уже запущена, то параметр mayInterruptIfRunning определяет, должен ли поток, выполняющий эту задачу, быть прерван при попытке остановить задачу.

После возврата этого метода последующие вызовы isDone() всегда будут возвращать значение true. Последующие вызовы isCancelled() всегда будут возвращать истину, если этот метод вернул истину.

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

Другими словами, .cancel(true) попытается прервать выполнение задачи, а .cancel(false) — нет.

Похоже, что result.get() все равно будет прервано, если вы вызовете .cancel(false), а задача еще даже не началась.

27.11.2014
  • Я это уже читал. Но когда я проверил код awaitDone, он проверяет Thread.interrupted(), что означает текущий поток, а не поток исполнителя, который будет прерван result.cancel(). 27.11.2014

  • 2

    Спасибо всем за ваш вклад. После стольких копаний я наконец нашел ответ.

    Это код на стороне сервера, и ошибка заключалась в клиентском коде, который прерывал сервер, если он не возвращал результат в указанный срок. Конечно, лимит времени клиента был меньше тайм-аута сервера.

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

    02.12.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..