1
Abstract: When we call the wait() method of the Java object or the sleep() method of the thread, we need to catch and handle the InterruptedException. If we improperly handle InterruptedException, unexpected consequences will occur!

This article is shared from the Huawei Cloud Community " [High Concurrency] Thinking about InterruptedException ", author: Binghe.

Preface

When we call the wait() method of the Java object or the sleep() method of the thread, we need to catch and handle the Interrupted Exception. If we improperly handle Interrupted Exception, unexpected consequences will occur!

Program case

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

package io.binghe.concurrent.lab08;

/**
 * @author binghe
 * @version 1.0.0
 * @description 线程测试中断
 */
public class Interrupted Task implements Runnable{

    @Override
    public void run() {

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

            try {
                Thread.sleep(100);
            } catch (Interrupted Exception e) {
                e.printStack Trace();
            }
        }
    }
}

The original intention of the above code is to check whether the thread is interrupted through the isInterrupted() method, and exit the while loop if it is interrupted. 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 is set, so that currentThread.isInterrupted() returns true, so that it can exit the while loop.

This doesn't seem to be a problem! But is this really the case? We create an Interrupted Test class for testing, the code is shown below.

package io.binghe.concurrent.lab08;

/**
 * @author binghe
 * @version 1.0.0
 * @description 测试线程中断
 */
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.
image.png

This is not the same as we thought! Different! Different! Why is this?

problem analysis

The above code clearly calls the thread's interrupt() method to interrupt the thread, but it has no effect. The reason is that when the thread's run() method is executed, most of the time is blocked on sleep(100). When other threads interrupt the execution thread by calling the interrupt() method of the execution thread, Interrupted will be triggered with a high probability Exception exception, while triggering Interrupted Exception exception, JVM will clear the interrupt flag bit of the thread at the same time. Therefore, at this time, the current Thread.isInterrupted() judged in the run() method will return false and will not exit. The while loop is now.

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

problem solved

after catching the exception in the while(true) loop in the run() method of the Interrupted Task class. Therefore, the correct Interrupted Task class code is shown below.

package io.binghe.concurrent.lab08;

/**
 * @author binghe
 * @version 1.0.0
 * @description 中断线程测试
 */
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 have added a line of code to the catch code block that catches Interrupted Exception.

currentThread.interrupt();
This allows us catch Interrupted Exception and reset the interrupt flag bit of the thread to interrupt the currently executing thread.

We run the main method of the Interrupted Test class again, as shown below.
image.png

Summarize

Be careful when handling Interrupted Exception. If an Interrupted Exception is thrown when the interrupt() method of the execution thread is called to interrupt the execution thread, the JVM will clear the interrupt flag bit of the execution thread at the same time when the Interrupted Exception is triggered. At this time, when the isInterrupted() method of the execution thread is called, false will be returned. At this point, the correct way to handle it is to catch Interrupted Exception in the run() method of the execution thread, and reset the interrupt flag bit (that is, in the catch code block that captures the Interrupted Exception exception, call the interrupt() of the current thread again. )method).

Click to follow, and get to know the fresh technology of Huawei Cloud for the first time~


华为云开发者联盟
1.4k 声望1.8k 粉丝

生于云,长于云,让开发者成为决定性力量