Почему я должен обернуть каждый вызов Thread.sleep() в оператор try/catch?
Я пытаюсь написать свою первую многопоточную программу на Java. Я не могу понять, почему мы требуем обработки исключений вокруг циклов for. Когда я компилирую без предложений try/catch, это дает исключение InterruptedException. (Вот сообщение:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type InterruptedException
)
Но при запуске с try/catch sysout в блоках catch никогда не отображается - это означает, что в любом случае такое исключение не было обнаружено!
public class SecondThread implements Runnable{
Thread t;
SecondThread(){
t = new Thread(this, "Thread 2");
t.start();
}
public void run(){
try{
for(int i=5 ; i>0 ; i--){
System.out.println("thread 2: " + i);
Thread.sleep(1000);
}
}
catch(InterruptedException e){
System.out.println("thread 2 interrupted");
}
}
}
public class MainThread{
public static void main(String[] args){
new SecondThread();
try{
for(int i=5 ; i>0 ; i--){
System.out.println("main thread: " + i);
Thread.sleep(2000);
}
}
catch(InterruptedException e){
System.out.println("main thread interrupted");
}
}
}
4 ответа
Метод Thread.sleep генерирует InterruptedException, если он обнаруживает, что в текущем потоке установлен флаг прерывания, рано выходит из спящего режима и позволяет использовать исключение для перемещения элемента управления где-либо за пределами текущего потока. Этот флаг устанавливается, только если что-то вызывает прерывание в потоке.
Поскольку ваша программа не вызывает прерывание ни в одном из потоков, InterruptedException не будет выброшено при запуске этой программы. Компилятор по-прежнему требует, чтобы вы перехватили исключение, поскольку это проверенное исключение, объявленное в методе sleep.
Если вы добавите такой метод в SecondThread
public void cancel() {
t.interrupt();
}
затем вызовите метод отмены в основном методе, например так:
public static void main(String[] args){
SecondThread secondThread = new SecondThread();
try{
for(int i=5 ; i>0 ; i--){
System.out.println("main thread: " + i);
Thread.sleep(2000);
secondThread.cancel();
}
}
catch(InterruptedException e){
System.out.println("main thread interrupted");
}
}
вы увидите println, где InterruptedException пойман в методе выполнения SecondThread.
Ошибки компиляции отображаются в eclipse на вкладке "Проблемы". Помимо того, что в редакторе вызываются подчеркиванием красного цвета, они отображаются при редактировании кода. При запуске этой программы любые исключения будут записаны в консоль вместе с выводом программы.
Вы должны справиться InterruptedException
в ваших темах, потому что вы вызываете методы, которые бросают InterruptedException
и Java спроектирован таким образом, что вы всегда должны обрабатывать проверенные исключения. То есть "в теме" не имеет значения.
Как сказано в JLS Sec 11.2:
Язык программирования Java требует, чтобы программа содержала обработчики для проверенных исключений, которые могут возникнуть в результате выполнения метода или конструктора (§8.4.6, §8.8.5).
Эти обработчики могут быть в форме try
/catch (InterruptedException)
, или же throws InterruptedException
; тем не менее, вы не можете использовать последний, потому что метод подписи void run()
не позволяет добавить проверенное исключение.
Таким образом, вы должны использовать try/catch.
Когда я компилирую без предложений try/catch, это дает исключение InterruptedException.
Исключения генерируются во время выполнения, а не во время компиляции, поэтому это не может быть правдой!
Возможно, вы получили ошибку компиляции Thread.sleep
может бросить InterruptedException
, но SecondThread.run
из которого Thread.sleep
называется, не объявляет, что может его кинуть. Поэтому компилятор не работает, потому что исключение не может никуда идти.
Обычно есть два способа решить это:
- поймать исключение или
- добавить
throws
пункт к вашему методу.
Последнее невозможно в этом случае, потому что SecondThread.run
переопределяет из Runnable.run
, который не объявляет, что выбрасывает какие-либо исключения. Так что вам нужно поймать исключение.
Если это не так или вы имели в виду "При запуске после компиляции без предложений try/catch это дает InterruptedException.", Пожалуйста, включите точное сообщение об ошибке, которое вы получили. На самом деле, вы всегда должны делать это, задавая вопросы здесь.
InterruptedException является проверенным исключением и должно быть перехвачено. В вашем коде он кидается sleep-методом. Поэтому, если вы не закроете его или не перезапустите, компилятор остановится, так как это проверенное исключение.
Но в вашем примере программы она никогда не будет запущена в нормальных условиях, поскольку вы не прерываете. Тем не менее, он предназначен для того, чтобы удостовериться в наличии кода для обработки, когда поток, который находится в спящем, ожидающем или иным образом состоянии "зомби", имеет установленный флаг прерывания и, таким образом, прерывается либо кодом, либо уровнем ОС. вызов.
Так что это на самом деле нужно ловить, и у него есть действительное использование.