Abstract: Let’s use a case study to explain in detail why threads that interrupt execution don’t work.

This article is shared by Huawei Cloud community “Why does it Not Work when threads are interrupted?” , author: Ice River.

When calling the Wait () method of a Java object or the sleep() method of a thread, you need to catch and handle the Interrupted Exception. If we do not handle the Interrupted Exception properly, we will have unexpected consequences! Today, we will use a case study to explain in detail why threads that interrupt execution do not work.

Application case

For example, in the following program code, the InterruptedTask class implements the Runnable interface, gets a handle to the current thread in the run() method, and checks whether the current thread has been interrupted through the isInterrupted() method in the while(true) loop. If the current Thread is Interrupted it exits the while(true) loop with a line of Thread.sleep(100) code that catches the Interrupted Exception. The entire code is shown below.

package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description thread test interrupts */ 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(); }}}}Copy the code

The intent of the above code is to check if the thread has been interrupted with the isInterrupted() method and exit the while loop if it has. Other threads by calling thread of execution of interrupt () method to interrupt execution threads, this will set the interrupt flag bit of thread of execution, so that the currentThread. IsInterrupted () returns true, so you can exit the while loop.

That doesn’t seem to be a problem! ** But is that really the case? ** We create a class for Interrupted Test, with the code shown below.

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

We run the main method, as shown below.

This is not what we expected! Not the same! Not the same! Why is that?

Problem analysis

The above code explicitly calls the thread’s interrupt() method to interrupt the thread, but it does nothing. The reason is that the thread’s run() method blocks most of the time on sleep(100). When other threads interrupt the thread by calling interrupt(), InterruptedException is most likely triggered. While trigger InterruptedException, the JVM will remove interrupt flag bit of thread at the same time, so, this time in the run () method of judging the currentThread. The isInterrupted () returns false, I would 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 way to do this is to reset the interrupt flag bit after catching the exception in the while(true) loop in the Run () method of the InterruptedTask class, so the correct code for the InterruptedTask class 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(); }}}}Copy the code

You can see that we have added a new line to the catch block that catches InterruptedException.

currentThread.interrupt();
Copy the code

This allows us to reset the thread’s interrupt flag after catching InterruptedException, thereby interrupting the currently executing thread.

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

conclusion

Use caution when handling InterruptedException. If InterruptedException is thrown when the thread of execution is interrupted by calling InterruptedException, The JVM also clears the interrupt flag of the executing thread and returns false when isInterrupted() is invoked. The correct response is to catch InterruptedException in the run() method of the thread of execution and reset the interrupt flag bit (in the catch block that catches InterruptedException, Reinvoke the interrupt() method of the current thread.

Click to follow, the first time to learn about Huawei cloud fresh technology ~