Boyang
Boyang

Reputation: 2566

Thread - Sleep and interrupt

Please first see this snippet:

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);
    }
}

This works as expected. I see countA to be approximately 2x of countB.

Now I add one line to the outer while loop:

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);
    }
}

Main thread interrupts anotherThread. After I do this, countA is no longer 2x countB. They always differ by one now.

Why so? How does sleep/interrupt work?

Upvotes: 2

Views: 1589

Answers (4)

Nathan Hughes
Nathan Hughes

Reputation: 96444

Interruption requires the thread being interrupted to cooperate, it has to look for signs that it has been interrupted and handle them. If you change anotherThread to this:

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();
        }
    }
});

then interrupting the thread will cause it to finish.

Calling interrupt sets the interruption flag, when the thread is sleeping and detects the flag is set then the sleep method throws an InterruptedException , also clearing the interrupt flag on the thread. Calling interrupt on the thread in the catch block is needed in order to restore the flag value. Then having the while loop test check the interrupt flag gives the thread the opportunity to quit.

Upvotes: 0

Chriss
Chriss

Reputation: 5639

If you interrupt anotherThread it will wakeup from its sleep. In other words it doesn't sleep 2sec but only 1sec like your Main-Thread (countA).

What interrupt does: It wakes a Thread that is in state sleep. The method sleep(int) will throw an InterrruptedException when interrupt() is called to indicate that the time not elapsed.

Upvotes: 0

Betlista
Betlista

Reputation: 10547

This is an addition to Buddy's answer, which is correct.

In first case you have

B    A
.    .
.    A
.    .
B    A
.    .
.    A
.    .
B    A

but with interrupt it changed to:

B    A (interrupts B, B continues in loop)
B    .
.    A (interrupts B again)
B    .
.    A
B    .
.    A
B    .
.    A

causing B not to wait 2 seconds...

Upvotes: 0

Buddy
Buddy

Reputation: 11038

Basically calling interrupt will wake up the thread from it's sleep call. Generally you would interrupt a thread because you want it to gracefully end... but in this case it just gets woken up, and then keeps on going within it's infinite loop.

Check out the docs for more information: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Upvotes: 3

Related Questions