3

我在 Java 中有一个线程调用

t.interrupt();

使 t (不同的线程)被中断。我希望“t”线程然后捕获一个,InterruptedException但 Eclipse 不会让我InterruptedException说它没有被抛出到 try 主体中。我怎样才能得到InterruptedException被调用?我用t.interrupt()错了吗?

4

4 回答 4

9

我真的不喜欢接受的答案,所以我想我会投入 0.02 美元。

我希望“t”线程然后捕获一个 InterruptedException,但 Eclipse 不会让我把一个 InterruptedException 放在说它没有被抛出到 try 主体中。如何调用 InterruptedException?我使用 t.interrupt() 错了吗?

重要的是要意识到t.interrupt()只在线程中设置中断位——它实际上并没有中断线程本身的处理。线程可以随时安全地中断。

引用Thread.interrupt()javadocs

  • 如果该线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法或 join()、join(long)、join(long, int) 时被阻塞, sleep(long), or sleep(long, int), 这个类的方法,那么它的中断状态会被清除并且会收到一个InterruptedException。

  • 如果该线程在可中断通道上的 I/O 操作中被阻塞,则该通道将被关闭,线程的中断状态将被设置,并且该线程将收到 java.nio.channels.ClosedByInterruptException。

  • 如果该线程在 java.nio.channels.Selector 中被阻塞,则该线程的中断状态将被设置,并且它将立即从选择操作返回,可能带有非零值,就像调用了选择器的唤醒方法一样。

  • 如果前面的条件都不成立,则将设置该线程的中断状态。

重要的是要补充一点,如果线程的中断位已设置,然后 wait()(和其他)被调用,那么wait()将立即抛出InterruptedException

所以你不能InterruptedExeption到处捕捉,因为只有某些方法会抛出它。如果您想查看线程是否已被中断(再次设置了中断位),那么正确的做法是直接使用Thread.getCurrentThread().isInterrupted(). 通常我们会执行以下操作:

while (!Thread.getCurrentThread().isInterrupted()) {
     // process stuff
     ...
     try {
         // here's an example of a method that throws InterruptedException
         Thread.sleep(100);
     } catch (InterruptedException e) {
         // catching InterruptedException actually clears the interrupt bit
         // so it is a good pattern to re-interrupt the thread immediately
         Thread.currentThread().interrupt();
         // now we decide what to do since we are interrupted
         break;
     }
}

关于这个主题有很多很好的问题和答案:

于 2013-07-25T14:03:07.117 回答
7

虽然其他答案是正确的,但更全面的解释是合适的。

线程只能在其执行的特定点被安全地中断(一般意义上的)。特别是,它可以在发出wait()调用或调用可以发出的服务时安全地中断wait()。这就是为什么InterruptedException是已检查异常而不是运行时(未检查)异常。允许线程在任何时候被任意中断会使执行变得不确定(至少这是指定 JVM 的方式)。有一种Thread#stop()方法被强烈反对,因为它导致的问题多于解决的问题。来自 Javadoc

这种方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未经检查的 ThreadDeath 异常沿堆栈传播的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。停止的许多用法应该由简单地修改一些变量以指示目标线程应该停止运行的代码替换。目标线程应该定期检查这个变量,如果变量指示它要停止运行,则以有序的方式从它的run方法返回。如果目标线程等待很长时间(例如在条件变量上),则应使用中断方法来中断等待。为什么不推荐使用 Thread.stop、Thread.suspend 和 Thread.resume?.

如果您需要中断正在运行的线程,则必须定期使用或轮询共享变量来轮询中断状态Thread.interrupted().isInterrupted()并自行采取适当的措施。

注意:上面的术语“中断”(除了作为方法名称的一部分)是一般意义上的,而不是调用的特定含义Thread#interrupt()

于 2013-07-24T17:08:02.430 回答
3

InterruptedException你可以调用Thread.interrupted()or而不是捕获Thread.getCurrentThread().isInterrupted()(前者将清除中断标志,后者不会),如果设置了中断标志,它将返回 true。InterruptedException如果你调用了一个抛出它的方法,你只能捕获它,比如sleep

于 2013-07-24T16:54:27.613 回答
2

InterruptedException 仅从特定的方法调用中抛出 - 主要是任何等待、睡眠或执行 I/O 的方法调用,因此不会从任何地方抛出。

如果您尝试中断的线程正在执行 CPU 密集型操作而不是 I/O,您将​​需要在其中进行Thread.getCurrentThread().isInterrupted()调用,否则目标线程可能永远不会注意到。

于 2013-07-24T16:54:45.133 回答