3 ways to cancel Java threads
- Thread cancels threads usually have the following ways:
- 1 Using the stop method to force the thread to stop it is a very unsafe way
- 2 Using volatile to set the marker bit to stop the thread, it is an incompletely reliable way
- 3 Use thread interrupt mechanism to stop threads in a collaborative manner
- Thread#stop stops thread, forcibly stop a running thread, the method is deprecated
- Thread#interrupt interrupt thread, request thread interrupt, set the thread's interrupt status to true
- Thread#isInterrupted Check the interrupt status of the thread, return the interrupt status of the current thread, and will not change the interrupt status of the thread.
- Thread#interrupted Check and clear the thread's interrupt state, return the current thread's interrupt state, and reset the thread's interrupt state to false, but it should be noted that this is a static method
Forced stop thread
- Thread#stop is not recommended to roughly stop threads, which may cause the following problems:
- 1 Thread#stop will immediately stop the remaining work in the run method, including logic in catch or finally, so it may cause some cleanup work to not be completed, such as the shutdown of files, databases, etc., which may lead to resource leakage problems.
- 2 Thread#stop will immediately release the locks held by the thread, which may cause the data to not be synchronized, data inconsistency may also cause the data structure being updated to be damaged, etc.
Set the volatile flag bit to stop the thread
- Using the volatile keyword to set the tag bits to stop threads is not completely reliable in some cases:
- 1. The simple use of the volatile keyword can ensure the visibility of variables (that is, one thread can make changes to variables to be seen in time by other threads), but it cannot guarantee the atomicity of the composite operation, which may cause the thread to end at an incorrect time point, resulting in unpredictable behavior.
- 2 If the thread is currently blocking or waiting, it will not respond to the change of the mark bit immediately, but will have to wait until it recovers from the blocking or waiting state before it has the opportunity to check the mark bit before it can start processing and end the process. There may be a certain lag at the time point.
Collaborative interrupt thread
- The thread interrupt mechanism is a collaborative mechanism that allows one thread to request another thread to stop the operation it is executing. The Thread#interrupt interrupt operation will not directly interrupt the thread (the thread will not be stopped immediately), but will only change the flag bit of the interrupt status of the target thread. The thread requested interrupt can check its own interrupt status in an appropriate position (such as loop conditions, before and after method calls, etc.) to determine whether it has been interrupted by checking its own interrupt status, and thus take corresponding actions to respond to the interrupt request. However, you can even choose to ignore it (because response interrupt is not a mandatory requirement, it depends on the specific implementation and requirements)
- Normally, when a thread checks itself and finds that the interrupt status is true, it means that the thread has been interrupted. At this time, it is necessary to process the interrupt request as soon as possible. You can choose to perform some operations such as cleaning resources, saving data, etc., and then end the thread.
- This design makes thread interrupts relatively safe because threads still have the opportunity to end their work in a reasonable way at the right time, rather than being forced to stop like Thread#stop
The thread task ends normally after execution
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { //Simulate threads to execute tasks for (int i = 0; i < 100000; i++) { ("Thread is running i=" + i); } //The thread ends normally after all tasks are executed ("---- Thread end ---"); } }; (); }
Add to the logic of request thread interrupt
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { //Simulate threads to execute tasks for (int i = 0; i < 100000; i++) { ("Thread is running i=" + i); } //ThreadThe #interrupt method requests the thread to be interrupted but will still execute all tasks ("----------------------------------); } }; (); //Demo logic try { //Wait for a while and interrupt the thread thread (10); } catch (Exception e) { (); } ("Request thread interruption"); //Request thread interruption for thread thread (); }
It means that just changing the interrupt state cannot achieve the effect of canceling the thread, and the logic of responding to the interrupt needs to be added.
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { //Simulate threads to execute tasks for (int i = 0; i < 100000; i++) { //The purpose is to allow the thread to check its interrupt status at the appropriate time and complete the logic of responding to the interrupt request if (().isInterrupted()) { ("The thread detects its interrupt status is true, so it is ready to stop"); //Release the resource and end the thread break; //It's OK to use return here } ("Thread is running i=" + i); } // ("---- Thread end ---"); } }; (); //Demo logic try { //Wait for a while and interrupt the thread thread (10); } catch (Exception e) { (); } ("Request thread interruption"); //Request thread interruption for thread thread (); }
Response interrupts in blocking states (such as method calls such as Object#wait, Thread#sleep, Thread#join, or Condition#await)
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { //Simulate threads to execute tasks for (int i = 0; i < 100000; i++) { try { (2); } catch (InterruptedException e) { //If a thread calls the interrupt method of the thread when it is in a blocking state, the blocking method will throw an InterruptedException exception, similar to the thread detecting its own interrupt state is true, which means that the logic of responding to interrupts needs to be added here. //The InterruptedException exception is thrown here, so that the thread can recover (wake up) from the blocking state (indicating that the blocking operation ends early due to interruption), and can have the opportunity to process the interrupt request before the thread ends. //In addition, the InterruptedException exception is thrown, the interrupt flag of the thread will be cleared (the interrupt status is reset to false) //So here you can do some logic to stop thread tasks from continuing execution (such as directly exiting the loop) or you can also call Thread#interrupt Reset the interrupt state (mark back to the interrupt state is true) and cooperate with Thread#isInterrupted() in the appropriate position to complete the logic of responding to the interrupt request. break; } ("Thread is running i=" + i); } // ("---- Thread end ---"); } }; (); //Demo logic try { //Wait for a while and interrupt the thread thread (10); } catch (Exception e) { (); } ("Request thread interruption"); //Request thread interruption for thread thread (); }
Threads can respond correctly to interrupt requests in blocking states
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { //Simulate threads to execute tasks for (int i = 0; i < 100000; i++) { //Check your own interrupt status in an appropriate location and complete the logic of responding to interrupt requests if (().isInterrupted()) { ("The thread detects its interrupt status is true, so it is ready to stop"); //Release the resource and end the thread break; //It's OK to use return here } try { (2); } catch (InterruptedException e) { //The interrupt flag bit will be cleared while throwing an InterruptedException (the interrupt status is reset to false) //So here you need to pay special attention to the interrupt flag that can be reset as needed, so that the interrupt request can be correctly responded to the interrupt request even in the blocking state (or it is easy to miss the interrupt request set by the externally) ().interrupt(); } ("Thread is running i=" + i); } // ("---- Thread end ---"); } }; (); //Demo logic try { //Wait for a while and interrupt the thread thread (10); } catch (Exception e) { (); } ("Request thread interruption"); //Request thread interruption for thread thread (); }
Summarize
- The stop method is not recommended to force stop threads, nor is it recommended to use volatile to set the mark bit to stop threads.
- The thread interrupt mechanism is an interactive cancellation method. One thread requests another thread to interrupt, and the other thread responds to the request interrupt of this thread (a thread should not be directly forced to interrupt or stop by other threads, but should be stopped by the thread itself, because the code of the task itself must be more clear than the code that issues the cancel request to understand how it should be cleared, released and ended. After all, the target thread knows better than the caller whether its own thread should be stopped, when to stop, and how to stop)
- The thread checks its own interrupt status or catches InterruptedException and then performs appropriate processing to respond to the interrupt.
- By rationally using thread interrupt mechanism, we can ensure that threads can be stopped safely and in an orderly manner, thereby avoiding resource leakage and some potential problems.
The above is the detailed content of the three ways to cancel Java threads. For more information about Java threads, please follow my other related articles!