Прерванная исключительная ситуация против isInterrupted в цикле while

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

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 разрыв цикла?

3 ответа

Решение

На самом деле ваш вопрос больше о 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 блок выполнен.

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

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

При возникновении InterruptedException статус прерывания потока сбрасывается. Если вы хотите восстановить статус прерванного потока, потому что вы хотите проверить флаг позже и сделать его истинным, вызовите 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(); 
}

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

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

Исключение не вызвано interrupt() метод, но по sleep() блокировка потока, который был сигнализирован как "прерванный". Это объясняется более подробно здесь. Смотрите также этот ответ.

Другие вопросы по тегам