2013-10-03 6 views
3

Я не понимаю, почему нить не бросает InterruptedException, когда прервана сама.Прерывание нити из себя

Я пытаюсь с следующий фрагмент кода:

общественного класса InterruptTest {

public static void main(String[] args) { 
    MyThread t = new MyThread(); 
    t.start(); 
    try { 
     t.join(); 
    } catch (InterruptedException ex) { 
     ex.printStackTrace(); 
    } 
} 

private static class MyThread extends Thread { 

    @Override 
    public void run() { 
     Thread.currentThread().interrupt(); 
    } 
} } 

В API Docs это говорит о interrupt() метода:

Если это поток блокируется при вызове методов wait(), wait (long) или wait (long, int) объекта класс, или Thread.join(), Thread.join (long), Thread.join (long, int), Thread.sleep (long) или Thread.sleep (long, int), методы этого класса, затем его статус прерывания будет очищен, и он получит InterruptedException.

ответ

3

Исключения всегда выбрасываются в их собственную нить. У вас есть два разных потока: ваш основной поток и тот, который вы создали. Не исключено, что исключение, заброшенное в MyThread, может быть обнаружено в главном.

+0

Спасибо за ответ, так что в этом случае, когда мне нужно оценить, прерывается ли другой поток, это флаг isInterrupted()? – iberck

+1

Да, это должно быть сделано. –

+1

Стоит упомянуть, что 'MyThread' также никогда не блокируется. Он умирает естественным образом, пытаясь прервать себя. – Muel

1

Зачем прерывать поток вообще? Просто используйте

return; 
0

Ты просто слишком быстро - попробуйте это:

private static class MyThread extends Thread { 

    @Override 
    public void run() { 
    try { 
     Thread.currentThread().interrupt(); 
     Thread.sleep(5000); 
    } catch (InterruptedException ex) { 
     Logger.getLogger(Test.class.getName()).log(Level.SEVERE, "Oops", ex); 
    } 
    } 
} 

я получаю:

Oct 04, 2013 12:43:46 AM test.Test$MyThread run 
SEVERE: Oops 
java.lang.InterruptedException: sleep interrupted 
at java.lang.Thread.sleep(Native Method) 
at test.Test$MyThread.run(Test.java:36) 

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

+0

Вы всегда можете распространять любое исключение из 'run()', если вы просто обернули его в некотором исключении 'RuntimeException' (например,' IllegalState..' или 'IllegalArg..') –

+1

может распространяться вне метода run(), но вы может только поймать его внутри нитки, которая бросает его, не так ли? – iberck

+1

@iberck существует несколько шаблонов для уведомления родительского потока, если в потоке было исключение. Вот вам [соответствующая дискуссия] (http://stackoverflow.com/questions/1369204/how-to-throw-a-checked-exception-from-a-java-thread) по этой теме. – inder

2

Я знаю, что это старый вопрос, но я думаю, что ответы выше на самом деле не совсем правильные. (за исключением @ Skylion's, который на самом деле не затрагивает вопрос ...) :)

Thread.interrupt() не выдает никаких исключений сам по себе. Это делает две вещи: во-первых он просто устанавливает внутренний прервал -flag, а затем он проверяет, является ли нить, что он был вызван на в настоящее время блокирования деятельности как wait(), sleep() или join(). Если он находит один, то он пробуждает этот метод и вызывает , что метод, чтобы выбросить исключение внутри потока, он был вызван по адресу (не из).

В случае, когда вы вызываете interrupt() из самой нити, этот поток, очевидно, не может быть в настоящий момент блокирован одним из этих вызовов, поскольку он в настоящий момент выполняет ваш вызов interrupt(). Таким образом, только внутренний прерван -flag установлен, и исключение не выбрасывается вообще.

В следующий раз, когда вы звоните один из методов блокировки (например, sleep() в @ OldCurmudgeon примере М.) из этого потока, что метод замечает прервал -flag и бросить InterruptedException.

Если вы никогда не назовете какой-либо из этих методов, ваш поток будет продолжать работать до тех пор, пока он не завершится каким-либо другим способом и никогда не выбросит InterruptedException. Это верно, даже если вы вызываете interrupt() из другого потока.

Таким образом, чтобы заметить, что ваш поток был прерван, вам необходимо либо часто использовать один из блокирующих методов, генерирующих InterruptedException, а затем бросить курить, когда вы получите один из этих исключений, или вам нужно часто звонить Thread.interrupted() проверить внутренний прерван -flag себя и бросить, если он когда-либо возвращается true.

Чтобы исключение быть выброшены методом join() в основном потоке, вам нужно вызвать interrupt() на , что нить, а не на MyThread, например, так:

public static void main(String[] args) { 
    MyThread t = new MyThread(); 
    t.start(); 
    try { 
     t.join(); 
    } catch (InterruptedException ex) { 
     System.out.println("Now it works:"); 
     ex.printStackTrace(); 
    } 
} 

private static class MyThread extends Thread { 

    private final Thread parentThread; 

    public MyThread() { 
     parentThread = Thread.currentThread(); 
    } 

    @Override 
    public void run() { 
     parentThread.interrupt(); // Call on main thread!!! 
    } 
} 
+0

Сегодня я узнал что-то новое. Спасибо. – OldCurmudgeon

Смежные вопросы