中断线程

ibe*_*rck 7 java multithreading

我不明白为什么线程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();
    }
} }
Run Code Online (Sandbox Code Playgroud)

在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.

Mar*_* A. 12

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

Thread.interrupt()不会抛出任何异常.它会做两件事情:首先,它只是设置一个内部中断 -flag,然后检查是否该线程,它被称为上正在阻塞的活动一样wait(),sleep()join().如果找到,则唤醒这个方法,并使该方法抛出线程,它被称为内部异常(不).

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

下次你sleep()从该线程中调用其中一个阻塞方法(比如在@ OldCurmudgeon的例子中)时,方法将注意到被中断的 -flag并抛出InterruptedException.

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

因此,要注意您的线程已被中断,您需要经常使用其中一种阻止方法,InterruptedException然后在收到其中一个异常时退出,或者您需要经常调用Thread.interrupted()以检查内部中断的 -flag并退出,如果它返回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!!!
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的例子,这应该是公认的答案!对示例代码的一项改进可能是添加 Thread.sleep(1); 在parentThread.interrupt()调用之后。当在我的机器上运行代码时,如果没有 Thread.sleep(1),则不会抛出 InterruptedException。可能是因为线程在中断调用后立即终止,并且主线程在 t.join() 调用被中断之前继续执行。 (2认同)

Cos*_*atu 0

请参阅@markus-a 的答案,了解此处应该接受的答案。(我的应该被删除,但在它被接受时我不能这样做)。


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

  • 实际上,MyThread 中甚至不会抛出异常(见下文)。 (3认同)