简体   繁体   English

我希望我的线程处理中断,但我无法捕获 InterruptedException,因为它是一个已检查的异常

[英]I want my thread to handle interruption, but I can't catch InterruptedException because it is a checked exception

I have a thread in Java which calls我在 Java 中有一个线程调用

t.interrupt();

making t (a different thread) be interrupted.使 t (不同的线程)被中断。 I want the "t" thread to then catch an InterruptedException but Eclipse won't let me put an InterruptedException in saying it's not thrown in the try body.我希望“t”线程然后捕获一个InterruptedException但 Eclipse 不会让我把一个InterruptedException说它没有被抛出到 try 主体中。 How can I get the InterruptedException to be called?如何调用InterruptedException Am I using t.interrupt() wrong?我使用t.interrupt()错了吗?

I really don't like the accepted answer so I thought I'd throw my $0.02 in.我真的不喜欢接受的答案,所以我想我会投入 0.02 美元。

I want the "t" thread to then catch an InterruptedException but Eclipse won't let me put an InterruptedException in saying it's not thrown in the try body.我希望“t”线程然后捕获一个 InterruptedException 但 Eclipse 不会让我把一个 InterruptedException 说它没有被抛出到 try 主体中。 How can I get the InterruptedException to be called?如何让 InterruptedException 被调用? Am I using t.interrupt() wrong?我使用 t.interrupt() 错了吗?

It is important to realize that t.interrupt() only sets the interrupted bit in a thread -- it doesn't actually interrupt the thread's processing per se.重要的是要意识到t.interrupt()只设置线程中的中断位——它实际上并没有中断线程本身的处理。 A thread can be interrupted at any time safely.线程可以随时安全地中断。

To quote from the Thread.interrupt() javadocs :引用Thread.interrupt() javadocs

  • If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.如果此线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法或 join()、join(long)、join(long, int) 方法时被阻塞、sleep(long) 或 sleep(long, int) 等方法,那么它的中断状态将被清除,并且它会收到一个 InterruptedException。

  • If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.如果此线程在可中断通道上的 I/O 操作中被阻塞,则通道将关闭,线程的中断状态将被设置,并且线程将收到 java.nio.channels.ClosedByInterruptException。

  • If this thread is blocked in a java.nio.channels.Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.如果此线程在 java.nio.channels.Selector 中被阻塞,则该线程的中断状态将被设置,并且它将立即从选择操作中返回,可能具有非零值,就像调用了选择器的唤醒方法一样。

  • If none of the previous conditions hold then this thread's interrupt status will be set.如果前面的条件都不成立,则将设置此线程的中断状态。

It is important to add that if the thread's interrupt bit has been set and then wait() (and others) is called, then the wait() will throw InterruptedException immediately.重要的是要补充一点,如果线程的中断位已经设置,然后调用了wait() (和其他),那么wait()将立即抛出InterruptedException

So you can't catch InterruptedExeption everywhere since only certain methods throw it.所以你不能在任何地方捕获InterruptedExeption ,因为只有某些方法会抛出它。 If you want to see if a thread has been interrupted (again has the interrupt bit set) then the right thing to do is to test for it directly with the Thread.getCurrentThread().isInterrupted() .如果您想查看线程是否已被中断(再次设置了中断位),那么正确的做法是直接使用Thread.getCurrentThread().isInterrupted() Typically we do something like the following:通常,我们会执行以下操作:

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;
     }
}

There are a number of good questions and answers on this topic:关于这个主题有很多很好的问题和答案:

While the other answers are correct, a fuller explanation is appropriate.虽然其他答案是正确的,但更全面的解释是适当的。

A thread can be safely interrupted (in the general sense of the word) only at specific points in its execution.一个线程只能在它执行的特定点被安全地中断(在这个词的一般意义上)。 In particular, it can be interrupted safely when it has issued a wait() call, or has invoked a service that can issue wait() .特别是,当它发出wait()调用或调用可以发出wait()的服务时,它可以安全地中断。 This is why InterruptedException is a checked exception and not a runtime (unchecked) exception.这就是InterruptedException是已检查异常而不是运行时(未检查)异常的原因。 Allowing a thread to be arbitrarily interrupted at any point would make execution non-deterministic (at least that's the way the JVM was specified).允许线程在任何时候被任意中断都会使执行变得不确定(至少 JVM 是这样指定的)。 There is a Thread#stop() method which is strongly deprecated because it causes more problems than it solves.有一个Thread#stop()方法被强烈反对,因为它引起的问题多于它解决的问题。 From the Javadoc来自 Javadoc

This method is inherently unsafe.这种方法本质上是不安全的。 Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack).使用 Thread.stop 停止线程会使其解锁所有已锁定的监视器(这是未经检查的 ThreadDeath 异常向上传播堆栈的自然结果)。 If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.如果先前受这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。 Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. stop 的许多用途应该被替换为简单地修改一些变量以指示目标线程应该停止运行的代码。 The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running.目标线程应该定期检查这个变量,如果变量表明它要停止运行,则以有序的方式从它的 run 方法返回。 If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.如果目标线程等待很长时间(例如在条件变量上),则应使用中断方法来中断等待。 For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?有关更多信息,请参阅为什么不推荐使用 Thread.stop、Thread.suspend 和 Thread.resume? . .

If you need to interrupt a running thread, then you must periodically poll the interrupted status with Thread.interrupted() or .isInterrupted() or poll a shared variable, and take appropriate action yourself.如果您需要中断正在运行的线程,那么您必须定期使用Thread.interrupted().isInterrupted()轮询中断状态或轮询共享变量,并.isInterrupted()采取适当的措施。

Note: The term "interrupted" above (except as part of a method name) is intended in the general sense, not the specific meaning of calling Thread#interrupt() .注意:上面的术语“中断”(作为方法名称的一部分除外)是一般意义上的,而不是调用Thread#interrupt()的具体含义。

Rather than catching InterruptedException you can call Thread.interrupted() or Thread.getCurrentThread().isInterrupted() (the former will clear the interrupted flag, the latter will not), which will return true if the interrupted flag is set.您可以调用Thread.interrupted()Thread.getCurrentThread().isInterrupted()而不是捕获InterruptedException (前者将清除中断标志,后者不会),如果设置了中断标志,它将返回 true。 You can only catch InterruptedException if you've called a method that throws it, like sleep如果您调用了抛出它的方法,例如sleep ,您只能捕获InterruptedException

InterruptedException is only thrown from specific method calls - mostly any method calls that wait, sleep or do I/O, so it wont be thrown out of anywhere. InterruptedException 仅从特定的方法调用中抛出 - 主要是等待、睡眠或执行 I/O 的任何方法调用,因此它不会从任何地方抛出。

if the Thread youre trying to interrupt is doing something CPU-internsive and not I/O, you will need to sprinkle Thread.getCurrentThread().isInterrupted() calls in there otherwise the target thread might never notice.如果您尝试中断的线程正在执行 CPU 内部而不是 I/O 的操作,则您需要在其中调用Thread.getCurrentThread().isInterrupted() ,否则目标线程可能永远不会注意到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM