1. Introduction
This article records some knowledge points about the interrupt mechanism in JAVA multithreading. It mainly consists of the difference between the stop method, interrupted() and isInterrupted() methods, and performs simple analysis from the implementation of the source code.
There are 3 ways to terminate running threads in JAVA
①The thread exits normally, that is, the run() method has been executed
② Use the stop() method in the Thread class to forcefully terminate the thread. However, the stop() method has expired and is not recommended to use it
③Use interrupt mechanism
There is nothing to do when the thread exits normally. The interrupt mechanism is introduced in detail below. Let’s first look at the source code of the stop() method. The key is the comments on the source code. It explains why stop() is not safe, which thread is stopped by the stop() method?
/*** Forces the thread to stop executing.* <p>* If there is a security manager installed, its <code>checkAccess</code>* method is called with <code>this</code>* as its argument. This may result in a* <code>SecurityException</code> being raised (in the current thread).* <p>* If this thread is different from the current thread (that is, the current* thread is trying to stop a thread other than itself), the* security manager's <code>checkPermission</code> method (with a* <code>RuntimePermission("stopThread")</code> argument) is called in* addition.* Again, this may result in throwing a* <code>SecurityException</code> (in the current thread).* <p>* The thread represented by this thread is forced to stop whatever* it is doing abnormally and to throw a newly created* <code>ThreadDeath</code> object as an exception.* <p>* It is allowed to stop a thread that has not yet been started.* If the thread is eventually started, it immediately terminates.* <p>* An application should not normally try to catch* <code>ThreadDeath</code> unless it must do some extraordinary* cleanup operation (note that the throwing of* <code>ThreadDeath</code> causes <code>finally</code> clauses of* <code>try</code> statements to be executed before the thread* officially dies). If a <code>catch</code> clause catches a* <code>ThreadDeath</code> object, it is important to rethrow the* object so that the thread actually dies.* <p>* The top-level error handler that reacts to otherwise uncaught* exceptions does not print out a message or otherwise notify the* application if the uncaught exception is an instance of* <code>ThreadDeath</code>.** @exception SecurityException if the current thread cannot* modify this thread.* @see #interrupt()* @see #checkAccess()* @see #run()* @see #start()* @see ThreadDeath* @see ThreadGroup#uncaughtException(Thread,Throwable)* @see SecurityManager#checkAccess(Thread)* @see SecurityManager#checkPermission* @deprecated This method is inherently unsafe. Stopping a thread with* Thread.stop causes it to unlock all of the monitors that it* has locked (as a natural consequence of the unchecked* <code>ThreadDeath</code> exception propagating up the stack). If* any of the objects previously protected by these monitors were in* an inconsistent state, the damaged objects become visible to* other threads, potentially resulting in arbitrary behavior. Many* uses of <code>stop</code> should be replaced by code that simply* modify some variable to indicate that the target thread should* stop running. The target thread should check this variable* regularly, and return from its run method in an orderly fashion* if the variable indicates that it is to stop running. If the* target thread waits for long periods (on a condition variable,* for example), the <code>interrupt</code> method should be used to* interrupt the wait.* For more information, see* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.*/@Deprecatedpublic final void stop() {stop(new ThreadDeath());}As commented above, lines 9 to 16 indicate that the stop() method can stop "other threads". The thread that executes the thread.stop() method is called the current thread, while the "other thread" is the thread represented by the object thread that calls the thread.stop() method.
like:
public static void main(String[] args) {MyThread thread = new MyThread...//....thread.stop();//..}In the main method, the current thread is the main thread. It executes to line 4 and wants to stop the "other thread" thread. This other thread is the thread represented by the thread object of the new MyThread class.
Lines 21 to 23 indicate that a thread that has not been started yet can be stopped. Its effect is: when the thread starts, it ends immediately.
The comments after line 48 deeply show why the stop() method is deprecated! Why it is insecure.
For example, threadA thread has monitors that are responsible for protecting certain critical resources, such as the amount of bank transfers. When the transfer process is in progress, the main thread calls the threadA.stop() method. As a result, the monitor is released, and the resources it protects (the amount of transfer) are likely to be inconsistent. For example, Account A has decreased by 100, while Account B has not increased by 100.
Second, interrupt mechanism
There are too many details on how to use the interrupt mechanism correctly in JAVA. Both interrupted() and isInterrupted() methods reflect whether the current thread is in an interrupted state.
① interrupted()
/*** Tests whether the current thread has been interrupted. The* <i>interrupted status</i> of the thread is cleared by this method. In* other words, if this method were to be called twice in succession, the* second call would return false (unless the current thread were* interrupted again, after the first call had cleared its interrupted* status and before the second call had examined it).** <p>A thread interruption ignored because a thread was not alive* at the time of the interrupt will be reflected by this method* returning false.** @return <code>true</code> if the current thread has been interrupted;* <code>false</code> otherwise.* @see #isInterrupted()* @revised .*/public static boolean interrupted() {return currentThread().isInterrupted(true);}From the comments in the source code, it tests the interrupt state of the current thread, and this method will clear the interrupt state.
②isInterrupted()
/*** Tests whether this thread has been interrupted. The <i>interrupted* status</i> of the thread is unaffected by this method.** <p>A thread interruption ignored because a thread was not alive* at the time of the interrupt will be reflected by this method* returning false.** @return <code>true</code> if this thread has been interrupted;* <code>false</code> otherwise.* @see #interrupted()* @revised .*/public boolean isInterrupted() {return isInterrupted(false);}As can be seen from the source code comments, the isInterrupted() method will not clear the interrupt state.
③Difference between interrupted() method and isInterrupted() method
As can be seen from the source code, both methods are called isInterrupted(boolean ClearInterrupted), except that one with the parameter is true and the other with the parameter is false.
/*** Tests if some Thread has been interrupted. The interrupted state* is reset or not based on the value of ClearInterrupted that is* passed.*/private native boolean isInterrupted(boolean ClearInterrupted);
Therefore, the first difference is that one clears the interrupt flag bit and the other does not clear the interrupt flag bit.
After analyzing the source code, you can see the second difference in the return statement:
public static boolean interrupted() {return currentThread().isInterrupted(true);}/************************/public boolean isInterrupted() {return isInterrupted(false);}interrupted() tests the interrupted state of the current thread. The isInterrupted() tests the thread represented by the object that calls the method. One is a static method (it tests the interrupt state of the current thread), and the other is an instance method (it tests the interrupt state of the thread represented by the instance object).
The following is a specific example to further clarify this difference.
There is a custom thread class as follows:
public class MyThread extends Thread {@Overridepublic void run() {super.run();for (int i = ; i < ; i++) {System.out.println("i=" + (i + ));}}}Let's first look at the example of the interrupted() method:
public class Run {public static void main(String[] args) {try {MyThread thread = new MyThread();thread.start();Thread.sleep();thread.interrupt();//Thread.currentThread().interrupt();System.out.println("Stop?="+thread.interrupted());//falseSystem.out.println("Stop?="+thread.interrupted());//false main thread is not interrupted!!! //...Line 5 starts the thread thread, and line 6 makes the main thread sleep for 1 second, so that the thread thread has a chance to obtain CPU execution.
After the main thread sleeps for 1s, it resumes execution to line 7 and requests to interrupt the thread thread.
Line 9 tests whether the thread is in an interrupted state. Which thread is being tested here? ? ? The answer is main thread. because:
(1) interrupted() tests the interrupt status of the current thread
(2) The main thread executes the 9th line statement, so the main thread is the current thread
Let's look at the example of the isInterrupted() method:
public class Run {public static void main(String[] args) {try {MyThread thread = new MyThread();thread.start();Thread.sleep();thread.interrupt();System.out.println("Does it stop?="+thread.isInterrupted());//trueOn line 8, isInterrupted() method called by the thread object. Therefore, the interrupt state of the thread represented by the thread object is tested. Since on line 7, the main thread requests to interrupt the thread thread, the result on line 8 is: true