以下简短的示例代码说明了我无法解释的行为
ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();
Thread t = new Thread(() -> {
long cnt = 0;
try {
while(!Thread.currentThread().isInterrupted()) {
testQueue.add(Math.random());
cnt++;
try {
Thread.sleep(100);
}catch (Exception e) {
System.out.println(String.format("inner interrupted inserted %d record", cnt));
}
}
} catch (Exception e) {
System.out.println(String.format("interrupted inserted %d record", cnt));
}
System.out.println(String.format("inserted %d record", cnt));
});
如果我调用t.interrupt()
来中断线程预期的行为是2条显示以下内容的行:
inner interrupted inserted %d record
inserted %d record
其中%d被替换为相应的值。但实际结果是
inner interrupted inserted %d record
如果我们将内部捕获移除到线程 ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();
Thread t = new Thread(() -> {
long cnt = 0;
try {
while(!Thread.currentThread().isInterrupted()) {
testQueue.add(Math.random());
cnt++;
Thread.sleep(100);
}
} catch (Exception e) {
System.out.println(String.format("interrupted inserted %d record", cnt));
}
System.out.println(String.format("inserted %d record", cnt));
});
然后我们得到输出interrupted inserted %d record
inserted %d record
正如预期的那样,现在外部捕获正在捕获InterruptException但是,如果我改为在第一个代码示例的最内层捕获中放置中断,如下所示:
ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();
Thread t = new Thread(() -> {
long cnt = 0;
try {
while(!Thread.currentThread().isInterrupted()) {
testQueue.add(Math.random());
cnt++;
try {
Thread.sleep(100);
}catch (Exception e) {
System.out.println(String.format("inner interrupted inserted %d record", cnt));
break; //this one
}
}
} catch (Exception e) {
System.out.println(String.format("interrupted inserted %d record", cnt));
}
System.out.println(String.format("inserted %d record", cnt));
});
产生了预期的行为。挡块的位置为什么会产生这种差异?
最佳答案
请参阅 Thread#interrupt
的文档:
If this thread is blocked in an invocation of [...] sleep(long), or sleep(long, int), [...], then its interrupt status will be cleared and it will receive an InterruptedException.
If none of the previous conditions hold then this thread's interrupt status will be set.
这意味着在您的示例中,
Thread#sleep
均会抛出异常XOR Thread.currentThread().isInterrupted()
给您true。因此,在第一个示例中,您捕获到异常,执行打印并在无限循环中输入/停留,因为
Thread.currentThread().isInterrupted()
始终为false
。在您的第二个示例中,try-catch没有嵌套在循环内,因此两次打印均会发生,并且线程将按预期终止。
在第三个示例中,您只是明确退出了循环。
仅供引用:您无需编写
System.out.println(String.format(...))
。有System.out.printf
,但请不要忘记\n
。
关于java - Java线程InterruptExceptioon处理仅在某些情况下阻止了进一步的代码执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64921763/