正如您所说,两者的区别在于一个清除线程的中断状态,另一个则不会。既然您已经知道了这一点,那么您真正想问的似乎是保留线程中断状态是否很重要。
首先,必须确定检查中断状态(或处理InterruptedException
)的代码是否被视为线程的“所有者”。如果是这样,在某些有限的情况下,可以适当地吞掉(或只是不抛出)InterruptedException
以及中断状态,因为所有者正在实现线程的取消策略(Goetz,《Java并发编程实践》,第143页)。
但在绝大多数情况下,包括Runnable
,相关代码都不是线程所有者,因此不能吞掉取消状态。在这种情况下,您有两个选择:
- 保留线程中断状态,但抛出
InterruptedException
。(这就是Thread.sleep()
的做法。)
- 保留中断状态。
对于Runnable
,您无法抛出已检查异常,因为run()
没有声明如此。 (反过来,我推测它是这样设计的,因为通常没有人去捕获它。)因此,您唯一的选择是保留取消状态。
鉴于上述解释,让我回到您的直接问题。首先,如果您想检查取消状态并保留它,那么编写以下代码会更容易:
if (Thread.currentThread().isInterrupted()) doSomething
than
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
doSomething;
}
此外,就像你最初的问题一样,如果你在一个while循环中使用Thread.interrupted()作为条件,在循环结束后你将无法确定它是因为Thread.interrupted()返回了true还是其他条件改变或者break语句运行了。所以在这种情况下使用Thread.currentThread().isInterrupted()实际上是你唯一的选择。(当然,你也可以编写循环,使其唯一的退出原因是线程已被中断,但这种代码容易出问题,因为在循环后你必须重新中断线程,如果有人后来改变了代码,也会因其他原因而退出循环,那么你就会在原本没有被中断的情况下中断线程。)
对于你的第二个问题,正如其他人所说,绝对不要使用Thread.currentThread().interrupted(),因为这很具有误导性。由于interrupted()是一个静态方法,在这种情况下如果你使用-Xlint编译器,则会得到一个有用的警告:
警告:[static] static method should be qualified by type name, Thread, instead of by an expression
类似的工具也可能会采取相同的做法,比如Eclipse会显示:
The static method interrupted() from the type Thread should be accessed in a static way
interrupt
方法的。 - Marko Topolnik