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

时间:2013-07-24 16:51:42

标签: java multithreading interrupt

我在Java中有一个调用

的线程
t.interrupt();

使t(不同的线程)中断。我希望“t”线程然后捕获一个InterruptedException但是Eclipse不会让我放一个InterruptedException来说它没有被抛入try体中。如何才能调用InterruptedException?我使用t.interrupt()错了吗?

4 个答案:

答案 0 :(得分:7)

我真的不喜欢接受的答案所以我认为我会把我的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)方法时阻塞了这个线程,加入(long,int),sleep(long)或sleep(long,int)这个类的方法,然后它的中断状态将被清除,并且它将收到InterruptedException。

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

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

  •   
  • 如果以前的条件都没有,那么将设​​置该线程的中断状态。

  •   

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

所以你无法在任何地方捕捉InterruptedException因为只有某些方法抛出它。正如其他人所提到的,如果你想看一个线程是否被中断(再次设置了中断位),那么正确的做法就是直接用InterruptedExeption进行测试。通常我们会执行以下操作:

Thread.getCurrentThread().isInterrupted()

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

答案 1 :(得分:6)

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

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

  

这种方法本质上是不安全的。使用Thread.stop停止一个线程会导致它解锁它已锁定的所有监视器(这是未经检查的ThreadDeath异常向上传播的自然结果)。如果先前受这些监视器保护的任何对象处于不一致状态,则受损对象对其他线程可见,可能导致任意行为。 stop的许多用法应该被简单修改某个变量的代码替换,以指示目标线程应该停止运行。目标线程应该定期检查此变量,并且如果变量指示它将停止运行,则以有序的方式从其run方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

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

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

InterruptedException仅从特定方法调用抛出 - 大多数方法调用等待,休眠或执行I / O,因此它不会被抛出任何地方。

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