下面的简短示例代码说明了我无法解释的行为
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
正如预期的那样,外部catch正在捕获interruptexception
但是,如果我将break放在第一个代码示例的最内部catch中,如下所示:
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));
});
产生预期的行为。
为什么挡块的位置会产生这样的差异?
1条答案
按热度按时间8yoxcaq71#
有关详细信息,请参阅文档
Thread#interrupt
:如果此线程在调用[…]sleep(long)或sleep(long,int),[…]时被阻塞,那么它的中断状态将被清除,并且它将接收一个interruptedexception。
如果前面的条件都不成立,那么这个线程的中断状态将被设置。
也就是说在你的例子中
Thread#sleep
抛出异常xorThread.currentThread().isInterrupted()
给你真实的感觉。因此,在第一个示例中,您捕获了异常,执行print并在无限循环中输入/保持为
Thread.currentThread().isInterrupted()
总是false
.在第二个示例中,try-catch没有嵌套在循环中,因此两个打印都会发生,线程也会按预期终止。
在第三个示例中,只需显式退出循环。
仅供参考:你不需要写作
System.out.println(String.format(...))
. 有System.out.printf
,但别忘了\n
.