3 回答
TA贡献1815条经验 获得超13个赞
这是因为中断标志如何为线程工作。
当您中断一个线程时,基本上只会发生一件事:设置中断标志,仅此而已。然后取决于该线程正在运行的代码是否确实执行了操作。
一般的想法是,如果可以的话,你会中止你正在做的事情并抛出一些合理的异常。
java 内置的一些方法保证这正是它们的工作方式。您可以轻松识别它们:它们都被声明为 throw InterruptedException。有许多方法在中断时故意未定义行为(这取决于操作系统):所有那些阻塞 I/O 方法都是这样的。如果您处于阻塞网络读取中并且中断读取时阻塞的线程,则可能会导致读取调用时出现 IOException,或者.. 不会。
更重要的是,当“处理”中断时(中止+抛出异常正在处理它!),标志被清除。
请注意,如果您使用检查标志的标准方法(即Thread.interrupted(). 这个方法检查你自己线程的中断标志并清除它。if使用这个:你已经写了一个声明或诸如此类的东西来处理中断这一事实意味着你已经处理了它。
因此,如果您只想返回以响应被打断,正确的代码是:
Runnable task = () -> {
while (!Thread.interrupted()) {
System.out.println("Executing");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
return;
}
}
};
无论中断何时发生,此方法都会退出。在 99.99% 的情况下,它会在阻塞睡眠时发生。然后标志将为假,并抛出异常。在不太可能发生的情况下,它会在其外部处理时发生,而 while 条件将拾取它。
请注意,如果您提高了中断标志并调用了类似的方法Thread.sleep,该方法将通过清除标志并抛出来立即InterruptedException完成执行。不管中断发生在哪里,上面的例子都会做同样的事情(静默退出run方法,中断标志将被清除)。
TA贡献1839条经验 获得超15个赞
InterruptedException并且Thread.isInterrupted()实际上非常独立。sleep()当您在长时间运行的循环中使用时,会引入并发症。你sleep(5000)实际上是清除你的isInterrupted标志并抛出InterruptedException.
如果您尝试以下操作,您会发现线程实际上没有InterruptException抛出。interrupt()
@Override public void run() {
int b = 0;
while (true) {
if (b++ == 0) System.out.println("running...");
}
}
教训是,您确实需要同时检查异常和标志,但它们不应该相互依赖。例如,您的示例捕获异常,但依赖标志退出循环。如您所见,这是行不通的。
您要么需要break在异常被捕获时退出 while 循环,要么在循环try/catch 之外(确保捕获异常使您脱离循环)。
因此,应提供以下任一服务:
while (!Thread.currentThread().isInterrupted()) { // out of the loop when flag is raised
try {
//......
}
catch (InterruptedException e) {
break;//exit loop when exception thrown
}
}
// Or:
try {
while (!Thread.currentThread().isInterrupted()) { // exit loop when flag is raised
//.....
}
}
catch (InterruptedException e) {
// no need to break, as we're already outside
}
TA贡献1895条经验 获得超7个赞
这是带有打印语句的代码。
public static void interrupted() throws InterruptedException {
Runnable task = () ->
{
while (true && !Thread.currentThread().isInterrupted()) {
System.out.println("task executing");
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// this prints false.
System.out.println(Thread.currentThread().isInterrupted());
}
}
};
一旦处理完中断状态,线程就不再被认为处于中断状态,因此循环继续。
添加回答
举报