2

Предположим, что у меня есть следующий код:Прерванный исключение против isInterrupted в время цикла

while(!Thread.currentThread().isInterrupted()){ 
    //do something 
    Thread.sleep(5000); 
} 

Теперь Thread.sleep бросает `InterruptedException так должно быть так:

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

    } 
} 

Если я ударил catch будет ли цикл while продолжить или мне нужно сделать Thread.currentThread().interrupt()? Если я вызову этот метод, не будет ли это также вызвано InterruptedException? В противном случае, как я получил исключение в первую очередь?

Кроме того, если у меня есть:

while (!Thread.currentThread().isInterrupted()){ 
    //do something 
    callMethod(); 
} 

private void callMethod(){ 
    //do something 
    try { 
    Thread.sleep(5000);  
    } catch(InterruptedException e){ 

    } 
} 

снова сломается мой while цикл?

+1

См. Здесь: http://stackoverflow.com/questions/9901649/after-catching-interruptedexception-why-thread-currentthread-isinterrupted –

+0

И здесь: http://stackoverflow.com/questions/1024651/do-i -have-to-worry-about-interruptedexceptions-if-i-dont-interrupt-anything-mys –

+0

Вы должны прочитать [Закон саботированного дверного звонка] (http://www.javaspecialists.eu/archive/Issue146.html). – OldCurmudgeon

ответ

0

На самом деле ваш вопрос скорее о try - catch - finally, чем о многопоточности.

1) Если sleep выбрасывает Exception, то catch блок будет выполнить, а затем цикл while продолжается.

2) Вы делаете одно и то же, как и в 1)

Чтобы выйти из цикла while, сделайте следующее:

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

} 

В этом случае, если Exception брошено, петля while остается и выполняется блок catch.

+0

+1: однако я предпочитаю перехватывать исключения внутри цикла, а затем прерывать или продолжать явно. – BigMike

+0

@BigMike Да, этот подход полностью соответствует понятию Java «Больше кода означает лучший код». –

+0

@MarkoTopolnik это просто, что я не хочу использовать блокирующий блок для управления потоком моей программы, если мне нужно выйти из цикла, я хочу быть тем, кто заявляет, что с явным перерывом, и что только ради кто наследует мой код завтра ... – BigMike

1

Thread.sleep() очистит «прерванный статус» перед бросанием InterruptedException. Вам нужно позвонить Thread.currentThread().interrupt() в блок catch, иначе условие while, скорее всего, не будет выполнено, потому что поток всегда будет «не прерываться», когда возвращается callMethod.

Исключение не вызвано методом interrupt(), а sleep(), блокирующим поток, который был сигнализирован как «прерванный». Это объясняется более подробно here. См. Также this answer.

0

Вызов прерывания по потоку сам по себе не вызывает исключения. Спящий или ожидающий, когда установлен флаг прерывания, вызывает вызовы InterruptedException.

Совершенно предсказуемо, что может вызывать InterruptedException, так что прерывание потока имеет контроль, и он может выбрать способ ответа. Это проверенное исключение, поэтому очевидно, что это делает. Это не похоже на ThreadDeath, который можно выбросить где угодно.

При срабатывании InterruptedException состояние прерывания потока сбрасывается. Если вы хотите восстановить прерванный статус потока, потому что вы хотите проверить флаг позже и иметь значение true, вызовите Thread.currentThread().interrupt(), чтобы установить его.

Во время перерыва ничего необычного не происходит, чтобы изменить порядок обработки команд.Так что если вы хотите поймать InterruptedException в петлю и установите флаг, чтобы выйти, вам необходимо сбросить флаг:

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, but still good style 
    Thread.currentThread().interrupt(); 
} 

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