请先看一下这个片段:
public static void main(String[] args) throws InterruptedException {
Thread anotherThread = new Thread(() -> {
Integer countB = 0;
while (true) {
try {
System.out.println("B count: " + ++countB);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
anotherThread.start();
Integer countA = 0;
while (true) {
System.out.println("A count: " + ++countA);
Thread.sleep(1000);
}
}
这可以按预期工作。我认为countA大约是countB的2倍。
现在我在外部while循环中添加一行:
public static void main(String[] args) throws InterruptedException {
Thread anotherThread = new Thread(() -> {
Integer countB = 0;
while (true) {
try {
System.out.println("B count: " + ++countB);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
anotherThread.start();
Integer countA = 0;
while (true) {
anotherThread.interrupt();
System.out.println("A count: " + ++countA);
Thread.sleep(1000);
}
}
主线程中断anotherThread。在我这样做之后,countA不再是2x countB。他们现在总是不同。
为什么这样?睡眠/中断如何工作?
答案 0 :(得分:3)
基本上调用interrupt
会从其sleep
调用中唤醒线程。通常你会打断一个线程,因为你希望它能够优雅地结束...但是在这种情况下它只是被唤醒,然后继续在它的无限循环内进行。
查看文档以获取更多信息: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
答案 1 :(得分:0)
这是对Buddy's answer的补充,这是正确的。
在第一种情况下,你有
B A
. .
. A
. .
B A
. .
. A
. .
B A
但有中断后改为:
B A (interrupts B, B continues in loop)
B .
. A (interrupts B again)
B .
. A
B .
. A
B .
. A
导致B不等待2秒......
答案 2 :(得分:0)
如果你打断 anotherThread ,它将从睡眠中唤醒。换句话说,它不会像主线程(countA)一样睡2秒,但只能睡1秒。
什么中断:它唤醒状态为 sleep 的线程。当调用 interrupt()时,方法sleep(int)将抛出 InterrruptedException 以指示未经过的时间。
答案 3 :(得分:0)
中断要求线程被中断配合,它必须寻找已被中断并处理它们的迹象。如果您将anotherThread更改为:
Thread anotherThread = new Thread(() -> {
Integer countB = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("B count: " + ++countB);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
});
然后中断线程将导致它完成。
调用中断设置中断标志,当线程处于休眠状态并检测到标志已设置时,sleep方法抛出InterruptedException,同时清除线程上的中断标志。需要在catch块中的线程上调用中断才能恢复标志值。然后通过while循环测试检查中断标志,让线程有机会退出。