Why does the thread I interrupt execution not work

Keywords: Java

Absrtact: in the form of a case, we will introduce in detail why the thread that interrupts execution does not work.

This article is shared from Huawei cloud community< Why doesn't it work when the thread is interrupted? >, author: Glacier.

When we call the wait() method of a Java object or the sleep() method of a thread, we need to catch and handle the Interrupted Exception. If we do not handle the Interrupted Exception properly, unexpected consequences will occur! Today, in the form of a case, we will introduce in detail why the thread that interrupts execution does not work.

Program case

For example, in the following program code, the InterruptedTask class implements the Runnable interface. In the run() method, get the handle of the current thread, and in the while(true) loop, use the isInterrupted() method to detect whether the current thread is interrupted. If the current thread is interrupted, exit the while(true) loop. At the same time, there is a line of Thread.sleep(100) code in the while(true) loop, And caught the Interrupted Exception. The entire code is shown below.

package io.binghe.concurrent.lab08;

/**
 * @author binghe
 * @version 1.0.0
 * @description Thread test interrupt
 */
public class InterruptedTask implements Runnable{

    @Override
    public void run() {

        Thread currentThread = Thread.currentThread();
        while (true){
            if(currentThread.isInterrupted()){
                break;
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

The original intention of the above code is to check whether the thread is interrupted through the isinterrupted () method. If it is interrupted, it will exit the while loop. Other threads interrupt the execution thread by calling the interrupt() method of the execution thread. At this time, the interrupt flag bit of the execution thread will be set, so that currentThread.isInterrupted() returns true, so that the while loop can be exited.

It doesn't look like a problem! But is that true? We create an Interrupted Test class for testing. The code is as follows.

package io.binghe.concurrent.lab08;

/**
 * @author binghe
 * @version 1.0.0
 * @description Test thread interrupt
 */
public class InterruptedTest {
    public static void main(String[] args){
        InterruptedTask interruptedTask = new InterruptedTask();
        Thread interruptedThread = new Thread(interruptedTask);
        interruptedThread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        interruptedThread.interrupt();
    }
}

We run the main method, as shown below.

This is different from what we thought! dissimilarity! dissimilarity! Why?

problem analysis

The above code explicitly calls the thread's interrupt() method to interrupt the thread, but it doesn't work. The reason is that the thread's run() method is blocked on sleep(100) most of the time. When other threads interrupt the executing thread by calling the interrupt() method of the executing thread, the InterruptedException exception will be triggered with a high probability. When the InterruptedException exception is triggered, the JVM will clear the interrupt flag bit of the thread at the same time. Therefore, At this time, the currentThread.isInterrupted() determined in the run() method will return false and will not exit the current while loop.

Now that the problem analysis is cleared, how do I interrupt the thread and exit the program?

Problem solving

The correct processing method should be to reset the interrupt flag bit after catching the exception in the while(true) loop in the run() method in the InterruptedTask class. Therefore, the code of the correct InterruptedTask class is as follows.

package io.binghe.concurrent.lab08;

/**
 * @author binghe
 * @version 1.0.0
 * @description Interrupt thread test
 */
public class InterruptedTask implements Runnable{

    @Override
    public void run() {

        Thread currentThread = Thread.currentThread();
        while (true){
            if(currentThread.isInterrupted()){
                break;
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                currentThread.interrupt();
            }
        }
    }
}

As you can see, we added a new line of code in the catch code block that caught the InterruptedException exception.

currentThread.interrupt();

This enables us to reset the interrupt flag bit of the thread after catching the InterruptedException exception, so as to interrupt the currently executing thread.

We run the main method of the InterruptedTest class again, as shown below.

summary

Be careful when handling the InterruptedException exception. If the InterruptedException exception is thrown when calling the interrupt() method of the execution thread to interrupt the execution thread, the JVM will clear the interrupt flag bit of the execution thread at the same time when the InterruptedException exception is triggered. At this time, false will be returned when calling the isInterrupted() method of the execution thread. At this time, the correct processing method is to catch the InterruptedException exception in the run() method of the execution thread and reset the interrupt flag bit (that is, call the interrupt () method of the current thread again in the catch code block that catches the InterruptedException exception).

 

Click focus to learn about Huawei cloud's new technologies for the first time~

Posted by justAnoob on Mon, 08 Nov 2021 21:23:43 -0800