先解释一下:
线程的中断状态基本上是一个布尔标志,由interrupt()设置为“true”。
该标志的当前状态可以使用Thread.currentThread().isInterrupted()读取。
如果可中断操作(如Object.wait() 或Thread.sleep())发现设置了中断标志
它会抛出一个InterruptedException,同时clear(设置为“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
完成我们的任务,然后返回。但是,这不是上面提到的良好做法,并且在某些情况下可能会导致问题。