Подтвердить что ты не робот

Как дифференцировать, когда выходите (длинный тайм-аут) для уведомления или таймаута?

Наличие этого объявления ожидания:

public final native void wait(long timeout) throws InterruptedException;

Он может выйти из InterruptedException или тайм-аутом или потому, что метод Notify/NotifyAll был вызван в другом потоке, исключение легко поймать, но...

Есть ли способ узнать, был ли причиной выхода из-за этого был тайм-аут или уведомление?

EDIT:

Это сложный способ, который мог бы работать (хотя мне это не нравится)

          long tBefore=System.currentTimeMillis();
          wait(TIMEOUT);
          if ((System.currentTimeMillis() - tBefore) > TIMEOUT) 
            { 
               //timeout
            }
4b9b3361

Ответ 1

Вы не можете различать эти два, если не указать какой-то дополнительный код. Например, добавив ThreadLocal Boolean, который установлен в true только на notify()

Но сначала вы должны убедиться, что ваша логика требует этой дифференциации.

Ответ 2

Есть еще одна причина, по которой уведомление может вернуть: ложное пробуждение. Это маловероятно, но возможно, потому что предотвращение побочных пробуждений очень дорого для некоторых аппаратных/ОС-комбинаций.

Из-за этого вам всегда нужно вызывать wait() в цикле и перепроверить условие, которое вы ожидаете. Во время этой работы легко проверять время ожидания в то же время.

Подробнее я рекомендую книгу "Java Concurrency In Practice". И используя конструкции более высокого уровня, которые сделают все это правильным для вас.

Ответ 3

Это не совсем точно ответит на вопрос, но это, вероятно, решит вашу проблему: используйте механизмы более высокого уровня concurrency. Ожидание/уведомление обычно более низкоуровневое, чем вы хотели бы, по этой причине среди многих других.

Например, если вы использовали BlockingQueue.poll(long, TimeUnit), вы могли бы проверить, является ли результат нулевым, чтобы узнать, не истечет ли срок.

Ответ 4

Не используйте System.currentTimeMillis(), используйте System.nanoTime().

Первый из них измеряет абсолютное время (основанное на системных часах) и может иметь любопытные результаты при изменении системного времени. Например: 5-секундное ожидание может иметь продолжительность часа, если часы будут перемещены назад на час или 10-минутное ожидание будет выполнено через 0 секунд, если часы будут перемещены вперёд.

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

Ответ 5

Невозможно прямо сказать - то есть вам придется добавить дополнительный код, чтобы определить это. Часто, когда вы ждете(), вы ждёте чего-то, что каким-либо образом изменяет состояние объекта. возможно, установив логическую переменную. В этом случае вы можете просто проверить состояние этой переменной, чтобы узнать, произошло ли событие или просто вышло из строя. Или вы можете посмотреть значение System.currentTimeMillis(), чтобы увидеть, что прошедшее время больше или равно периоду таймаута - если это так, это будет ключ, который вы, вероятно, запустили (хотя это не абсолютная гарантия). Или, если прошедшее время меньше, чем период ожидания, вы, разумеется, не выбыли. Помогает ли это?

Ответ 6

Исключение не выбрасывается при уведомлении и тайм-ауте.

Я думаю, что лучше использовать java.lang.concurrent объекты синхронизации пакета вместо использования Object.wait().