The thread interrupt mechanism provides a method for waking a thread from a blocking wait, trying to interrupt the target thread's existing processing flow and responding to new commands. Java leaves this freedom to developers, and we should make good use of it.
Today we will talk about the interrupt mechanism of Java threads.
The thread interrupt mechanism provides a method that has two common uses:
Wake up the thread from blocking waiting and make corresponding "controlled interrupt" processing.
Try to inform the target thread: Please interrupt the existing processing flow and respond to new commands.
Take the first purpose as an example, please see the following code:
synchronized (lock) { try { while (!check()) { lock.wait(1000); } } catch (InterruptedException e) { e.printStackTrace(); }}This code uses the wait/notify mechanism provided by Java. The thread execution of lock.wait() will block. There are three situations to restore the thread to run.
1. Timeout 1000ms ends, and the next code is executed normally.
2. Another thread executes the following code to wake up actively
synchronized (lock) { lock.notifyAll(); // or lock.notify();}This will also execute the next code normally.
3. Another thread that is required to wait for is "interrupt"
// Get the reference to the waiting thread Thread a;a.interrupt();
Thread a that is "interrupted" will throw an InterruptedException exception at lock.wait().
To sum up, you can think object.wait() is doing these things internally:
boolean checkTimeout = timeout > 0;Thread current = Thread.currentThread();lock.addWaiter(current);while (!current.isNotified()) { if (current.isInterrupted()) { current.clearInterrupted(); throw new InterruptedException(); } if (checkTimeout) { if (timeout == 0) break; timeout--; }}This is not completely accurate, because wait does not use this "busy polling" method to check, but the logic of judging flag bits is correct.
Let's start with the "manually issue interrupt" operation mentioned above
// sun.nio.ch.Interruptiblepublic interface Interruptible { void interrupt(Thread var1);}// java.lang.Threadprivate volatile Interruptible blocker;private final Object blockerLock = new Object();public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); b.interrupt(this); return; } } interrupt0();}// Just to set the interrupt flagprivate native void interrupt0();It can be seen that thread.interrupt() first judges permissions, and then actually calls interrupt0() to set the thread's interrupt flag. If the current thread has nio's Interruptible, it will also call back.
Note that interrupt0() just sets the thread's interrupt flag.
What happens when a thread is not blocking and is not in areas that are not controlled by Java program logic, such as object.wait(), thread.join(), Thread.sleep()? The answer is that nothing will happen, and whether the thread is interrupted can only be known by actively checking the interrupt flag.
How to check? Thread exposes two interfaces, Thread.interrupted() and thread.isInterrupted().
// java.lang.Threadpublic static boolean interrupted() { return currentThread().isInterrupted(true);}public boolean isInterrupted() { return isInterrupted(false);}private native boolean isInterrupted(boolean clearInterrupted);It can be seen that both rely on the internal isInterrupted(boolean), which will return whether the thread is interrupted and clear the interrupt flag as needed.
When a function call blocks, the Java library function marks throws InterruptedException in the blocking source signature and requires the write try catch to handle interrupts.
When the thread blocks, as mentioned above, Java checks for the interrupt flag, clears it first, and then throws an InterruptedException.
// java.lang.Objectpublic final void wait() throws InterruptedException { wait(0);}public final native void wait(long timeout) throws InterruptedException;If a thread receives an InterruptedException and then executes the code that will throw a blocking, it will continue to block like "no matter". Because Java clears the interrupt flag internally!
We often write the following three types of code that handle InterruptedException:
Handle the InterruptedException to the upper layer for processing.
public void foo() throws InterruptedException { synchronized (lock) { lock.wait(); }}InterruptedException Reset the interrupt flag bit.
try { synchronized (lock) { lock.wait(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); //break; }Finish your work first, and then throw an InterruptedException again.
public void bar() throws InterruptedException { InterruptedException ie = null; boolean done = false; while (!done) { synchronized (lock) { try { lock.wait(); } catch (InterruptedException e) { ie = e; continue; } } done = true; } if (ie != null) { throw ie; }}If a thread ignores the interrupt flag and InterruptedException, it still runs well. But this is contrary to our original intention of designing multithreading. We want threads to cooperate harmoniously and in an orderly manner to achieve specific functions, so controlled threads should respond to interrupts. And we should make good use of this freedom left by Java to developers.
The above is all the relevant knowledge about the Java thread interrupt mechanism introduced to you this time. If you don’t understand anything, you can discuss it in the message area below. Thank you for your support for Wulin.com.