Kiedy funkcja Thread.sleep języka Java zgłasza wyjątek InterruptedException?

110

Kiedy funkcja Thread.sleep języka Java zgłasza wyjątek InterruptedException? Czy można to bezpiecznie zignorować? Nie robię wielowątkowości. Chcę tylko poczekać kilka sekund przed ponowną próbą wykonania jakiejś operacji.

Manki
źródło
1
Zależy, w jakim sensie masz na myśli „ignoruj”. InterruptedExceptionWyjątkiem jest złapany, więc nie można kompilować chyba że uchwyt lub zadeklarować ten typ wyjątku na każdą metodą, która łączy czy śpi Thread, czy rozmów wait()na temat Object.
8bitjunkie

Odpowiedzi:

41

Generalnie NIE powinieneś ignorować wyjątku. Spójrz na następujący artykuł:

Nie połykaj przerw

Czasami zgłoszenie InterruptedException nie jest opcją, na przykład gdy zadanie zdefiniowane przez Runnable wywołuje metodę przerywaną. W takim przypadku nie możesz ponownie zgłosić InterruptedException, ale nie chcesz też nic robić. Gdy metoda blokowania wykryje przerwanie i zgłosi InterruptedException, usuwa stan przerwania. Jeśli złapiesz InterruptedException, ale nie możesz go ponownie wyrzucić, powinieneś zachować dowody na to, że przerwanie wystąpiło, aby kod znajdujący się wyżej na stosie wywołań mógł dowiedzieć się o przerwaniu i odpowiedzieć na nie, jeśli chce. Zadanie to jest realizowane przez wywołanie przerwania () w celu „ponownego przerwania” bieżącego wątku, jak pokazano na Listingu 3. Przynajmniej, gdy złapiesz InterruptedException i nie wyrzucisz go ponownie, przerwij bieżący wątek przed powrotem.

public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;

    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }

    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }
}

Zobacz cały artykuł tutaj:

http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-

Benny Bottema
źródło
38

Jeśli InterruptedExceptionzostanie wyrzucony, oznacza to, że coś chce przerwać (zwykle zakończyć) ten wątek. Jest to wyzwalane przez wywołanie interrupt()metody wątków . Metoda wait wykrywa to i generuje, InterruptedExceptionaby kod catch mógł obsłużyć żądanie zakończenia natychmiast i nie musi czekać, aż upłynie określony czas.

Jeśli używasz go w aplikacji jednowątkowej (a także w niektórych aplikacjach wielowątkowych), ten wyjątek nigdy nie zostanie wyzwolony. Ignorowanie go przez posiadanie pustej klauzuli catch, nie polecam. Rzutowanie InterruptedExceptionczyści stan przerwania wątku, więc jeśli nie zostanie prawidłowo obsłużony, informacja zostanie utracona. Dlatego proponuję uruchomić:

} catch (InterruptedException e) {
  Thread.currentThread().interrupt();
  // code for stopping current task so thread stops
}

Co ponownie ustawia ten stan. Następnie zakończ wykonanie. To byłoby poprawne zachowanie, nawet trudne, nigdy nie używane.

Lepiej byłoby dodać to:

} catch (InterruptedException e) {
  throw new RuntimeException("Unexpected interrupt", e);
}

... oświadczenie do bloku catch. Zasadniczo oznacza to, że nigdy nie może się to zdarzyć. Więc jeśli kod zostanie ponownie użyty w środowisku, w którym może się to zdarzyć, będzie narzekać.

chrześcijan
źródło
5
Asercje w Javie są domyślnie wyłączone . Więc lepiej po prostu rzucić RuntimeException.
Evgeni Sergeev
11

Biuletyn Java Specialists (który mogę bez zastrzeżeń polecić) zawierał interesujący artykuł na ten temat i jak sobie radzić z InterruptedException. Warto go przeczytać i przetrawić.

Brian Agnew
źródło
1
Co to mówi?
theonlygusti
5

Metody takie jak sleep()i wait()klasy Threadmogą generować plik InterruptedException. Stanie się tak, jeśli ktoś inny będzie threadchciał przerwać to, threadco czeka lub śpi.

użytkownik7805041
źródło
3

Solidnym i łatwym sposobem obsługi tego w kodzie jednowątkowym byłoby przechwycenie go i pobranie go w RuntimeException, aby uniknąć konieczności deklarowania go dla każdej metody.

starblue
źródło
-7

InterruptedExceptionZwykle jest generowany, gdy sen jest przerywany.

BrutalOst
źródło
13
To źle, ponieważ to nie sam sen jest przerywany, ale prowadzący go Wątek. Przerwano to stan wątku. To po prostu prowadzi do wyjścia z metody snu.
ubuntudroid