线程 - 睡眠和中断

时间:2015-12-02 07:20:13

标签: java multithreading sleep interrupted-exception interruption

请先看一下这个片段:

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。他们现在总是不同。

为什么这样?睡眠/中断如何工作?

4 个答案:

答案 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循环测试检查中断标志,让线程有机会退出。