线程 - 睡眠和中断
Thread - Sleep and interrupt
请先看这个片段:
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);
}
}
主线程中断另一个线程。在我这样做之后,countA 不再是 2x countB。他们现在总是相差一个。
为什么会这样? sleep/interrupt 是如何工作的?
基本上调用 interrupt
会从它的 sleep
调用中唤醒线程。通常你会中断一个线程,因为你希望它优雅地结束......但在这种情况下,它只是被唤醒,然后在它的无限循环中继续前进。
查看文档了解更多信息:
https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
这是对 的补充,是正确的。
第一种情况你有
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 秒...
如果您中断 anotherThread 它将从睡眠中唤醒。换句话说,它不会像您的主线程 (countA) 那样休眠 2 秒,而只会休眠 1 秒。
中断的作用:唤醒处于睡眠状态的线程。当 interrupt() 被调用时,方法 sleep(int) 将抛出一个 InterrruptedException 以指示时间未过去。
中断需要被打断的线程配合,它要寻找自己被打断的迹象并进行处理。如果将 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();
}
}
});
然后中断线程将导致它完成。
调用中断设置中断标志,当线程休眠并检测到标志设置时,睡眠方法抛出一个 InterruptedException ,同时清除线程上的中断标志。为了恢复标志值,需要在 catch 块中的线程上调用中断。然后让 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) {
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);
}
}
主线程中断另一个线程。在我这样做之后,countA 不再是 2x countB。他们现在总是相差一个。
为什么会这样? sleep/interrupt 是如何工作的?
基本上调用 interrupt
会从它的 sleep
调用中唤醒线程。通常你会中断一个线程,因为你希望它优雅地结束......但在这种情况下,它只是被唤醒,然后在它的无限循环中继续前进。
查看文档了解更多信息: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
这是对
第一种情况你有
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 秒...
如果您中断 anotherThread 它将从睡眠中唤醒。换句话说,它不会像您的主线程 (countA) 那样休眠 2 秒,而只会休眠 1 秒。
中断的作用:唤醒处于睡眠状态的线程。当 interrupt() 被调用时,方法 sleep(int) 将抛出一个 InterrruptedException 以指示时间未过去。
中断需要被打断的线程配合,它要寻找自己被打断的迹象并进行处理。如果将 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();
}
}
});
然后中断线程将导致它完成。
调用中断设置中断标志,当线程休眠并检测到标志设置时,睡眠方法抛出一个 InterruptedException ,同时清除线程上的中断标志。为了恢复标志值,需要在 catch 块中的线程上调用中断。然后让 while 循环测试检查中断标志,让线程有机会退出。