English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
The thread interruption mechanism provides a method to wake up a thread from a blocked waiting state, attempt to interrupt the target thread's current processing flow, and make it respond to a new command. Java leaves this freedom to developers, and we should make good use of it.
Today, let's talk about the interruption mechanism of Java threads.
The thread interruption mechanism provides a method, with two common uses:
Wake up the thread from the blocked waiting state and perform the corresponding 'controlled interruption' handling.
Attempt to inform the target thread: please interrupt the current processing flow and respond to a new command.
For example, let's take a look at the following code for the first use case:
synchronized (lock) { try { while (!check()) { lock.wait(1000); } } e.printStackTrace(); } }
This code uses Java's wait/The notify mechanism, when a thread executes lock.wait(), will block, and there are three situations that allow the thread to resume running.
1Timeout 1000ms ends, and the next line of code is executed normally.
2Another thread executes the following code to actively wake up
synchronized (lock) { lock.notifyAll(); // or lock.notify(); }
This will also execute the next line of code normally.
3Another thread requests to 'interrupt' the waiting thread
// Obtain the reference of the waiting thread Thread a; a.interrupt();
Thread a, interrupted by 'interrupt', will throw an InterruptedException at lock.wait().
In summary, you can consider that object.wait() internally does the following things:
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 entirely accurate because wait does not use this 'busy-wait' method for checking, but the logic for judging the flag is correct.
Let's start exploring the operation of 'manual interruption' mentioned above
// sun.nio.ch.Interruptible public interface Interruptible { void interrupt(Thread var1); } // java.lang.Thread private 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 flag private native void interrupt0();
It can be seen that thread.interrupt() first checks the permission, then actually calls interrupt0() to set the interrupt flag of the thread, and if the current thread has the nio Interruptible, it will also call it back.
Note that interrupt0() only sets the interrupt flag of the thread.
When a thread is not blocked, not in areas such as object.wait(), thread.join(), Thread.sleep() that are not controlled by the Java program logic, what will happen? The answer is nothing will happen, whether the thread is interrupted can only be learned by actively checking the interrupt flag.
How to check? Thread exposes two interfaces, Thread.interrupted() and thread.isInterrupted().
// java.lang.Thread public 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 returns whether the thread is interrupted and clears the interrupt flag as needed.
When a function call may cause a block, Java library functions mark the blocking source signature with throws InterruptedException and require writing try-catch to handle the interruption.
When a thread is blocked, as described above, Java checks the interrupt flag, clears it first, and then throws InterruptedException.
// java.lang.Object public final void wait() throws InterruptedException { wait(0); } public final native void wait(long timeout) throws InterruptedException;
If a thread receives InterruptedException and still executes blocking code afterward, it will continue to block as if nothing happened. Because Java clears the interrupt flag internally!
We commonly write the following three types of code to handle InterruptedException:
The InterruptedException is delegated to the upper level for processing.
public void foo() throws InterruptedException { synchronized (lock) { lock.wait(); } }
Reset the interruption flag when encountering InterruptedException.
try { synchronized (lock) { lock.wait(); } } Thread.currentThread().interrupt(); //break; }
First, finish the task, and then re-throw InterruptedException.
public void bar() throws InterruptedException { InterruptedException ie = null; boolean done = false; while (!done) { synchronized (lock) { try { lock.wait(); } ie = e; continue; } } done = true; } if (ie != null) { throw ie; } }
If a thread ignores the interruption flag and InterruptedException, it can still run very well. But this goes against our original intention of designing multi-threading, where we hope that threads can collaborate harmoniously and orderly to achieve specific functions. Therefore, the controlled thread should respond to interruptions. And Java leaves this freedom to developers, which we should make good use of.
That's all the content of the Java thread interruption mechanism that we have introduced to you this time. If you still have any questions, you can discuss them in the comment area below. Thank you for your support of the Yell Tutorial.
Statement: The content of this article is from the network, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.)