Лучший способ обработки InterruptedException

Я использую Thread.sleep(10000); следовательно, мне нужно обработать InterruptedException. Я могу вызвать Thread.currentThread.interrupt(), а затем выдать исключение вызывающему классу, или я могу напрямую передать его вызывающему классу, или есть ли лучший способ справиться с этим?


person Element    schedule 01.03.2016    source источник
comment
Вы уверены, что вам нужен Thread.sleep? В 99% случаев он вам не нужен и не должен им пользоваться.   -  person Neijwiert    schedule 01.03.2016
comment
Я опрашиваю сообщения из файла, и мне приходится ждать 10 секунд перед каждой итерацией, поэтому я использую sleep(). Можете ли вы предложить мне лучший способ   -  person Element    schedule 01.03.2016
comment
Как информация записывается в файл? Есть ли у вас какой-либо контроль над этим?   -  person Neijwiert    schedule 01.03.2016
comment
Нет, я подключен только к пути к файлу для получения данных.   -  person Element    schedule 01.03.2016
comment
Вероятно, вам лучше использовать Timer или ScheduledExecutorService, чем переводить поток в спящий режим.   -  person bradimus    schedule 01.03.2016
comment
Блокирует ли процесс записи файл или разрешает совместное чтение/запись?   -  person Neijwiert    schedule 01.03.2016
comment
@neijwiert разрешено читать и писать   -  person Element    schedule 01.03.2016
comment
Оформить rxjava-file, как указано здесь stackoverflow.com/a/31202832/2160152   -  person cheffe    schedule 01.03.2016
comment
@MohitChandak - Рассматривали ли вы возможность использования пакета java.nio.file, который предоставляет API уведомлений об изменении файлов, который называется Watch Service. Этот API позволяет вам 2 зарегистрировать каталог в службе часов. При регистрации вы сообщаете сервису, какие типы событий вас интересуют: создание файла, удаление или модификация. Когда служба обнаруживает интересующее событие, оно перенаправляется в зарегистрированный процесс. Зарегистрированный процесс имеет поток (или пул потоков), предназначенный для наблюдения за любыми событиями, для которых он зарегистрирован. Когда приходит событие, оно обрабатывается по мере необходимости.   -  person The Roy    schedule 01.03.2016
comment
@DROY Это хорошая альтернатива. Но в моем случае более одного объекта пытаются изменить один и тот же файл. Я хочу, чтобы только один из них мог изменять файл, а другие - нет. Поэтому я использовал нить. Даже если я использую процесс, который вы предлагаете, мне все равно придется обрабатывать что-то вроде прерывания.   -  person Element    schedule 01.03.2016


Ответы (4)


Если у вас есть выделенный поток, который зацикливается и опрашивается, это звучит для меня как что-то, что нужно завершить, когда программа завершится; если это не поток демона (подразумевается, что вы довольны тем, что он уходит без возможности очистки или закрытия ресурсов), он должен иметь возможность обрабатывать прерывания. Использование WatchService кажется хорошей идеей, но код, использующий WatchService, все равно должен знать, как обрабатывать прерывания.

Если вы пишете Runnable или Callable, который находится в спящем режиме, вы можете использовать InterruptedException для выхода из любого цикла, который вы делаете, или вы можете поймать исключение и восстановить флаг прерывания, чтобы следующая проверка флага прерывания (с использованием Thread.currentThread().isInterrupted()) могла видим, что поток был прерван:

while(!Thread.currentThread().isInterrupted()){  
   //do something   
   try{  
     Thread.sleep(5000);    
   } catch(InterruptedException e){  
        Thread.currentThread().interrupt();
   }
}

В качестве альтернативы вы можете использовать InterruptedException, чтобы выйти из цикла:

try {
    while (!Thread.currentThread().isInterrupted()) {
        // do something
        Thread.sleep(5000);
    }
} catch (InterruptedException e) {
    // flag value is not used here
    Thread.currentThread().interrupt(); 
}

Если вы разрабатываете объект, который предполагается вложить в другие объекты, создайте исключение и добавьте его в сигнатуру метода. В качестве примера просмотрите документ API для классов в пакетах java.util.concurrent, таких как BlockingQueue, посмотрите, как такие методы, как put и offer, вызывают InterruptedException. Когда объекты, созданные для параллелизма, компонуются вместе, они должны взаимодействовать (и следить за тем, чтобы они не теряли отслеживание состояния прерывания), чтобы убедиться, что они могут очищаться и завершаться реагирующим образом.

person Nathan Hughes    schedule 01.03.2016
comment
Разве while (true) в альтернативе не будет понятнее? - person Esteve; 15.09.2020
comment
@Esteve: в первом примере исключение перехватывается внутри цикла, поэтому ему необходимо проверить флаг прерывания, чтобы выйти из цикла while. в альтернативном примере это не так важно. но если флаг уже установлен до входа в цикл, я бы предпочел сразу проверить флаг, а не вводить метод сна. - person Nathan Hughes; 15.09.2020

В большинстве обычных кодов вы не должны использовать sleep. Часто есть лучший способ сделать то, что вы хотите.

Я могу вызвать Thread.currentThread.interrupt()

Это полезно, если вы хотите продолжить как обычно, но без ожидания.

а затем бросить исключение для вызывающего класса

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

или я могу напрямую бросить его в вызывающий класс

В этом случае можно и не ловить.

или есть лучший способ справиться с этим?

Это зависит от того, почему вы ожидаете, что поток будет прерван. если я не ожидаю прерывания, я оборачиваю его AssertionError

person Peter Lawrey    schedule 01.03.2016

Как правило, повторите бросок, если можете, или установите флаг прерывания, если вы не можете повторить бросок.

Хорошая статья на эту тему: http://www.ibm.com/developerworks/library/j-jtp05236/

из которых наиболее подходящим отрывком будет:

Когда блокирующий метод обнаруживает прерывание и выдает InterruptedException, он сбрасывает состояние прерывания. Если вы перехватываете InterruptedException, но не можете его повторно сгенерировать, вы должны сохранить доказательства того, что прерывание произошло, чтобы код, находящийся выше в стеке вызовов, мог узнать о прерывании и отреагировать на него, если он захочет.

person metlos    schedule 01.03.2016

Я использую Thread.sleep(10000); следовательно, мне нужно обработать InterruptedException.

Не обязательно. Есть умные способы справиться с InterruptedException, а есть глупые способы. Если ваш поток никогда не будет быть прерван, то какая разница, какой путь вы выберете?

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

Но иногда мы просто хотим написать быстрый хак, который мы собираемся использовать один раз, а затем выбросить...

person Solomon Slow    schedule 01.03.2016