我在Java中有一个调用
的线程t.interrupt();
使t(不同的线程)中断。我希望“t”线程然后捕获一个InterruptedException
但是Eclipse不会让我放一个InterruptedException
来说它没有被抛入try体中。如何才能调用InterruptedException
?我使用t.interrupt()
错了吗?
答案 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()
调用,否则目标线程可能永远不会注意到。