先解释一下:
线程的中断状态基本上是一个布尔标志,它被设置为“真” interrupt()
。此标志的当前状态可以使用读取Thread.currentThread().isInterrupted()
。
如果可中断操作(如Object.wait()
or Thread.sleep()
)发现中断标志集,它将抛出一个InterruptedException
并同时清除(设置为“false”)标志,如下所示:
if ( Thread.interrupted() ) { throw new InterruptedException(); }
注意并记住Thread.interrupted()
隐式清除中断标志!这意味着,当你catch( InterruptedException ie) {...}
被执行时,线程本身并不知道它被中断了。
也就是说,让我们看两个例子:
首先是支持取消的任务示例。在这里,我们并不关心任务在中止之前进行了多远:
public void run() {
int x = 0;
try {
while (x < 10) {
Thread.sleep(1000); // Some interruptible operation
x++;
}
System.out.println("x = " + x);
} catch (InterruptedException ie) {
System.out.println("Interrupted: x = " + x);
// We know we've been interrupted.
// Let the caller know it, too:
Thread.currentThread().interrupt();
}
}
此代码尝试从 0 到 10 计数 x。如果没有中断,它将完成并输出“x = 10”。但是,如果线程在两者之间被中断,InterruptedException
则会抛出 ,中止正在进行的递增 x 的任务。在这种情况下,输出可能是从“Interrupted: x = 0”到“Interrupted: x = 9”的任何内容,具体取决于线程何时中断。
请注意,最好在退出之前恢复线程的中断标志,否则此run()
方法的调用者将看不到中断状态。
现在,如果我们的任务完全执行至关重要,这样输出将始终为“x = 10”,这意味着该任务不支持取消,我们需要另一种方法:
public void run() {
int x = 0;
boolean wasInterrupted = false; // <- This is the local variable to store the interruption status
while (x < 10) {
wasInterrupted = wasInterrupted || Thread.interrupted(); // not really needed in this case, but for the sake of completeness...
try {
Thread.sleep(1000); // <- Some interruptible operation
} catch (InterruptedException e) {
wasInterrupted = true;
}
x++;
}
System.out.println("x = " + x);
if ( wasInterrupted ) {
Thread.currentThread().interrupt();
}
}
在这种情况下,即使在InterruptedException
任务完成之后,我们也会继续处理。为了保持良好状态,如果我们检测到中断,我们会存储该条件,wasInterrupted
以便我们可以在从方法返回之前正确设置中断标志。
这就是意思
应该将中断状态保存在本地,并在返回之前将其恢复。
它说“应该”,因为我们没有严格要求以这种方式处理中断——我们也可以忽略任何中断InterruptedException
,完成我们的任务,然后返回。但是,这不是上面提到的良好做法,并且在某些情况下可能会导致麻烦。