Почему я должен оборачивать каждый вызов 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");
        }
    }
}

person Sergio Gliesh    schedule 02.06.2016    source источник
comment
When I compile without the try/catch clauses it gives an InterruptedException: нет, это дает ошибку, что вы не перехватываете это проверенное исключение - это сильно отличается от того, что компилятор выдает вам исключение.   -  person OrangeDog    schedule 02.06.2016
comment
Когда я компилирую, он говорит следующее: Исключение в потоке main java.lang.Error: Нерешенная проблема компиляции: тип необработанного исключения InterruptedException at MainThread.main(MainThread.java:10)   -  person Sergio Gliesh    schedule 02.06.2016
comment
@SergioGliesh: отредактируйте свой вопрос, не пишите его в комментарии.   -  person Andy Turner    schedule 02.06.2016
comment
Если вы не хотите обрабатывать InterruptedException, один из вариантов — использовать Guava Uninterruptibles.sleepUninterruptibly(), который правильно подавляет InterruptedException, но (как следует из названия) означает, что вы больше не можете прерывать сон, что часто не то, что вы действительно хотите делать.   -  person dimo414    schedule 02.06.2016


Ответы (4)


Метод Thread.sleep выдает InterruptedException, если обнаруживает, что текущий поток имеет установленный флаг прерывания, рано пробуждаясь от спящего режима и позволяя вам использовать исключение для перемещения управления куда-то за пределы текущего потока. Этот флаг устанавливается, только если что-то вызывает прерывание в потоке.

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

Если вы добавите такой метод в 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 на вкладке «Проблемы», помимо того, что их вызывают в редакторе, подчеркивая красным, они отображаются при редактировании кода. Когда вы запускаете эту программу, любые исключения будут записаны в консоль вместе с выводом программы.

person Nathan Hughes    schedule 02.06.2016

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

Но в вашей примерной программе она никогда не будет сброшена в нормальных условиях, поскольку вы не прерываете ее. Тем не менее, он нужен для того, чтобы убедиться, что существует код обработки, когда поток, который спит, ожидает или иным образом находится в состоянии «зомби», имеет установленный флаг прерывания и, таким образом, прерывается либо кодом, либо на уровне ОС. вызов.

Так что на самом деле это необходимо для ловли, и у него есть правильное применение.

person Richard Tyregrim    schedule 02.06.2016


Когда я компилирую без предложений try/catch, он дает InterruptedException.

Исключения генерируются во время выполнения, а не во время компиляции, так что это не может быть правдой!

Вероятно, ошибка компиляции, которую вы получали, заключалась в том, что Thread.sleep может генерировать InterruptedException, но SecondThread.run, из которого вызывается Thread.sleep, не объявляет, что может генерировать его. Поэтому компилятор дает сбой, потому что исключение никуда не денется.

Обычно есть два способа решить эту проблему:

  • поймать исключение или
  • добавьте в свой метод предложение throws.

Последнее в данном случае невозможно, потому что SecondThread.run переопределяет Runnable.run, который не заявляет, что выдает какое-либо исключение. Итак, вам нужно поймать исключение.

Если это не так или вы имели в виду "При запуске после компиляции без предложений try/catch выдается InterruptedException", укажите точное сообщение об ошибке, которое вы получили. На самом деле, вы всегда должны делать это, когда задаете вопросы здесь.

person Oebele    schedule 02.06.2016
comment
Я даже не знаю, как определить ошибки времени компиляции и времени выполнения в Eclipse! В любом случае это то, что говорит: Исключение в потоке main java.lang.Error: Нерешенная проблема компиляции: Тип необработанного исключения InterruptedException at MainThread.main(MainThread.java:10) - person Sergio Gliesh; 02.06.2016
comment
Если это происходит во время компиляции: это ошибка времени компиляции. Если это происходит во время работы кода: это ошибка времени выполнения. Подсказка: когда написано Нерешенная проблема компиляции, это ошибка времени компиляции. - person Andy Turner; 02.06.2016