中断线程

时间:2013-10-03 23:22:58

标签: java multithreading

我不明白为什么线程在中断时不会抛出InterruptedException

我正在尝试使用以下代码段:

  

public class 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文档中,它使用interrupt()方法:

  

如果在调用Object类的wait(),wait(long)或wait(long,int)方法或Thread.join(),Thread.join(long)的方法中阻止此线程,Thread.join(long,int),Thread.sleep(long)或Thread.sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。

4 个答案:

答案 0 :(得分:10)

我知道这是一个老问题,但我认为上面的答案实际上并不完全正确。 (除了@ Skylion,它没有真正解决这个问题......):)

Thread.interrupt()本身不会抛出任何异常。它做了两件事:首先它只是设置一个内部的被打断的 -flag,然后它检查它被调用的线程当前是否阻塞{{3 },wait()sleep()。如果它找到一个,那么它会唤醒该方法,并导致该方法将异常抛出到 on (而非来自)

的线程中。

如果您从线程本身调用interrupt(),那么该线程显然当前无法阻止其中一个调用,因为它正在执行您的interrupt()调用。因此,只设置内部中断的 -flag,并且不会抛出任何异常。

下次你从该线程调用其中一个阻止方法(如@ OldCurmudgeon示例中的sleep())时, 方法会注意到被中断 - 标记并抛出join()

如果你没有调用任何这些方法,你的线程将继续运行,直到它以其他方式终止,并且永远不会抛出InterruptedException。即使您从其他线程调用interrupt()也是如此。

因此,要注意您的线程已被中断,您需要经常使用一种抛出InterruptedException的阻止方法,然后在收到其中一个异常时退出,或者您需要经常调用InterruptedException自行检查内部中断的标志,如果它返回 true 则退出。但您也可以完全忽略异常和Thread.interrupted()的结果并保持线程运行。所以,interrupt()可能有点含糊不清。它根本不一定“中断”(如“终止”)线程,它只是向线程发送一个信号,线程可以根据需要处理或忽略。就像CPU上的硬件中断信号(可能是名称来源)。

要在主线程中使用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!!!
    }
}

答案 1 :(得分:3)

异常总是在自己的线程上抛出。您有两个不同的主题:主线程和您创建的主线程。 MyThread中抛出的异常无法在主要异常中捕获。

答案 2 :(得分:1)

为什么要中断线程?只需使用

return;

答案 3 :(得分: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不会抛出任何异常。