Background
- Because using the Stop method to stop a thread from being very violent can cause a series of problems, a gentle approach is proposed: Ask the other one not to execute, which is the interrupt mode.
- There is also the scenario of writing a program that requires a pause for a period of time, and then calling Thread.Sleep (), but the compiler or IDE has reported that it did not process the checked interruptedexception. For interruptedexception, a common way to deal with this is "eat" it: capture it and do nothing.
- In order to wait for certain conditions to arrive in a child thread, you call Thread.Sleep (10000) and expect the thread to wake up after 10 seconds of sleep, but if this particular condition arrives early, notify a thread in sleep. Also, for example, the thread blocks itself by calling the child thread's join method to wait for the child thread to end, but the child thread finds itself not able to end in a short period of time, so it needs to find a way to tell the main line Cheng to wait for me. In these cases, an interruption is required.
- It's very easy to start a thread in Java, and in most cases I'm going to let a thread run its own task and then stop on its own, but sometimes we need to cancel something, like when you download it on the web and sometimes you need to cancel it. It is not easy to implement a thread-safe outage because Java does not support the mechanism of a secure fast interrupt thread.
Interrupt
Each thread has a Boolean property associated with it that represents the interrupt state of the thread (interrupted status). When the interrupt state is initially false, one of the following two scenarios occurs when another thread breaks a thread by calling Thread.Interrupt (). (1) If that thread is executing a low-level interruptible blocking method, such as Thread.Sleep (), Thread.Join (), or object.wait (), then it will unblock and throw interruptedexception. (2) Otherwise, interrupt () simply sets the interrupt state of the thread. Code running in the interrupted thread can then poll the interrupt state to see if it is being requested to stop what it is doing. The interrupt state can be read by thread.isinterrupted () and can be read and purged by an operation called thread.interrupted ().
Interrupts are a collaborative mechanism. When a thread breaks another thread, the interrupted thread does not have to immediately stop what it is doing. Instead, a break is a polite request to another thread to stop what it is doing when it is willing and convenient. Some methods, such as Thread.Sleep (), take such requests very seriously, but each method does not necessarily respond to interrupts. For interrupt requests, a method that does not block but still takes a long time to execute can poll the interrupt state and return early when it is interrupted. You can ignore interrupt requests at will, but doing so can affect the response.
One of the benefits of interrupted collaboration features is that it provides greater flexibility in constructing a removable activity safely. We seldom want an activity to stop immediately, and if the activity is canceled while an update is in progress, the program data structure may be in an inconsistent state. Interrupts allow a removable activity to clean up work in progress, restore invariants, and notify other activities that it will be canceled before terminating.
Related methods
This.interrupt ()
Interrupts the thread that calls the method, unless the current thread is interrupting itself, otherwise the CheckAccess method might throw a SecurityException exception.
(1) If the current thread is blocked by calling the wait () of object, or thread's join and sleep methods, the break state is cleared and the interrruptedexception exception is thrown.
(2) If the thread is blocked due to Interruptiblechannel IO operation, the channel shuts down, the thread sets the interrupt state, and the thread receives an closedinterruptexception exception.
(3) If the thread is blocked due to selector, the thread will be in a broken state and returned immediately from the selection operation, possibly a non-0 value.
In addition, the thread will be set to the interrupt state.
Overall: The interrupt method has two functions: (1) The interrupt state of the strong thread is set to True (2) to let the blocked thread throw the interruptedexception exception (while the interrupt state is false).
This is very important. Thus, for those blocking methods (such as wait () and sleep ()), when another thread calls interrupt () to break the thread, the thread exits from the blocking state and throws an interrupt exception. In this way, we can catch the interrupt exception and do some processing based on the actual situation of the thread exiting from the blocking method.
Note: A thread that is not CPU-bound will not be able to set its own interrupt status, resulting in a interruptedexception exception.
For example, thread A gets a lock into the synchronization code block, but the wait () method is blocked because of insufficient conditions. At this point, thread B executes the threada.interrupt () request in thread A, at which point A is thrown interruptedexception, and we can catch the exception in the catch and handle it accordingly (for example, to throw it further)
This.isinterrupted ()
Detects if the thread that called the method is interrupted and the interrupt state is not cleared. Once the thread is interrupted, the method returns True, and once the method throws an exception such as sleep, it clears the interrupt state, and the method returns false.
Package Com.huawei.thread;public class Test30 {public static void main (string[] args) {Thread t = thread.currentthread (); S Ystem.out.println ("1:" + t.isinterrupted ()); T.interrupt (); System.out.println ("2:" + t.isinterrupted ()); System.out.println ("3:" + t.isinterrupted ()); try {thread.sleep (2000); System.out.println ("Not interrted ...");} catch (Exception e) {System.out.println ("interrupted ..."); System.out.println ("4:" + t.isinterrupted ());} System.out.println ("5:" + t.isinterrupted ());}}
Thread.interrupted ()
Detects if the current thread is interrupted, and the interrupt status is cleared (that is, reset to false), because it is a static method and therefore cannot be used on a particular thread, only the interrupt state of the thread that called it is reported, and if the method is called two times, the second time is generally returned false, if the thread does not survive, False is returned.
Package Com.huawei.thread;public class Test31 {public static void main (string[] args) {System.out.println ("1:" + thread.i Nterrupted ()); Thread.CurrentThread (). interrupt (); System.out.println ("2:" + thread.interrupted ()); System.out.println ("3:" + thread.interrupted ());}}
Blocking methods
When a method throws a interruptedexception, it not only tells you that it can throw a particular check exception, but also tells you something else. For example, it tells you that it is a blocking (blocking) method, and if you respond properly, it will try to eliminate blocking and return as early as possible.
The blocking method differs from the usual method of running for a longer period of time. The general method's completion depends only on what it wants to do, and whether there are enough compute resources available (CPU cycles and memory). The completion of the blocking method also depends on some external events, such as timer expiry, I/O completion, or the action of another thread (releasing a lock, setting a flag, or putting a task in a work queue). The general approach ends when their work is done, and the blocking methods are more difficult to predict because they depend on external events. Blocking methods can affect responsiveness because it is difficult to predict when they will end.
Blocking methods can be useful because they cannot be terminated because they cannot wait for an event to wait for them to be canceled , which is often useful if a long-running non-blocking method can be canceled. A cancel operation refers to an operation that can be terminated externally before it is completed normally. The interrupt mechanism provided by thread and supported by Thread.Sleep () and object.wait () is a cancellation mechanism that allows one thread to request that another thread stop what it is doing. When a method throws Interruptedexception, it is telling you that if the thread that executes the method is interrupted, it will try to stop the thing it is doing while returning early and by throwing interruptedexception indicating that it returns early. A well-behaved blocking library method should be able to respond to interrupts and throw interruptedexception so that it can be used in a cancel activity without affecting the response.
non-disruptive blocking methods
Not all blocking methods throw interruptedexception. The input and output stream classes block waiting for I/O completion, but they do not throw interruptedexception and do not return prematurely if interrupted. However, for socket I/O, if a thread closes the socket, the blocking I/O operation on that socket ends prematurely and throws a socketexception. Non-blocking I/O classes in Java.nio also do not support interruptible I/O, but you can also cancel blocking operations by closing the channel or requesting wake on selector. Similarly, an attempt to acquire an internal lock (into a synchronized
block) cannot be interrupted, but the Reentrantlock supports an interruptible fetch pattern.
Common methods for dealing with thread interrupts that do not support interrupts
If a thread is blocked due to a synchronous memory IO operation, the interrupt request does not throw a interruptedexception, how can this thread be interrupted?
Package Com.huawei.thread;import Java.io.ioexception;import Java.io.inputstream;import Java.net.Socket;public class Test32 extends Thread {public static final int buf_size = 512; Socket Socket;inputstream in;public TEST32 (socket socket) throws IOException {this.socket = socket;this.in = Socket.getin Putstream ();} @Overridepublic void Interrupt () {try {socket.close ();} catch (IOException e) {} finally {Super.interrupt ()}} @Overridepublic void Run () {try {byte[] buf = new Byte[buf_size];while (true) {int count = In.read (BUF); if (Count < 0) {break;} else if (Count > 0) {}}} catch (IOException e) {}}}
By overwriting the Thread.Interrupt method, the socket is closed when the interrupt method is called, and if the Read method is blocked at this point, the IOException exception is thrown, and the thread task ends.
Handling Interrruptedexception
(1) If throwing interrruptedexception means that a method is a blocking method, then invoking a blocking method means that your method is also a blocking method, and there should be some strategy to handle interrruptedexception. Usually the easiest strategy is to throw the interrruptedexception yourself, which will allow the method to respond to interrupts and simply add interruptedexception to the throws clause.
public class Taskqueue { private static final int max_tasks = +; Private blockingqueue<task> queue = new linkedblockingqueue<task> (max_tasks); public void Puttask (Task R) throws Interruptedexception { queue.put (r); } Public Task Gettask () throws Interruptedexception { return queue.take ();} }
(2) Sometimes you need to do some cleanup before propagating the exception, in which case you can capture interruptedexception, perform cleanup, and then throw an exception.
public class Playermatcher {private Playersource players; Public Playermatcher (Playersource players) {this.players = players; } public void Matchplayers () throws Interruptedexception {try {Player playerone, playertwo; while (true) {Playerone = Playertwo = null; Wait for the players to arrive and start a new game Playerone = Players.waitforplayer (); Could throw IE Playertwo = Players.waitforplayer (); Could throw IE startnewgame (Playerone, playertwo); }} catch (Interruptedexception e) {//If we got one player and were interrupted, put that Player back if (playerone! = null) Players.addfirst (Playerone); Then propagate the exception throw E; } }}
(3) Do not eat interrupts: sometimes throwing interruptedexception is not appropriate, for example, when a task defined by runnable calls an interruptible method, in which case the interruptedexception cannot be re-thrown, Because the Run method of the Runnable interface does not allow exceptions to be thrown. When a blocking method detects an interrupt and throws a interruptedexception but cannot re-throw it, the evidence of the interruption should be preserved so that the higher-level code in the call stack knows the interrupt and responds to the interrupt, which can be called by calling interrupt () To re-interrupt the current thread to complete.
public class Taskrunner implements Runnable { private blockingqueue<task> queue; Public Taskrunner (blockingqueue<task> queue) { this.queue = queue; } public void Run () { try { while (true) { Task task = Queue.take (timeunit.seconds); Task.execute (); } } catch (Interruptedexception e) { //Restore the interrupted status Thread.CurrentThread (). interrupt (); }}
pending Interrupts
The implementation of methods such as sleep checks that the blocking thread is interrupted, it terminates the thread amicably, and throws a Interruptedexception exception. In another case, if a thread is interrupted before calling a method such as sleep, then the interrupt is called a pending interrupt, which immediately throws a Interruptedexception exception when a method called sleep has just been invoked.
Package Com.huawei.thread;public class Test29 {public static void main (string[] args) {Thread.CurrentThread (). Interrupt (); Long start = System.currenttimemillis (); try {thread.sleep (40000); System.out.println ("Not interrupted ...");} catch (Exception e) {System.out.println ("interrupted ..."); System.out.println (System.currenttimemillis ()-Start);}}
The results of the operation are as follows:
In this mode, the main thread interrupts itself. In addition to setting the interrupt flag (which is the internal flag of thread) to true, there is no other effect. The thread is interrupted, but the main thread is still running, the main thread continues to monitor the real-time clock and enters the try block, and once the Sleep () method is called, it will notice the existence of the pending interrupt and throw interruptexception. The execution jumps to the catch block and prints the information that the thread is interrupted. Finally, the time difference is calculated and printed.
Example 1
Package Com.huawei.thread;public class Test27 {public static void main (string[] args) {try {MyThread1 t = new MyThread1 (); T.start (); Thread.Sleep (+); T.interrupt (); Middle Thread T} catch (Interruptedexception e) {System.out.println ("main catch"); E.printstacktrace ();} SYSTEM.OUT.PRINTLN ("End Main");}} Class MyThread1 extends Thread {@Overridepublic void Run () {for (int i = 1; i < 500000; i++) {if (thread.interrupted ()) {System.out.println ("Stop and Exit ..."); System.out.println ("I:" + i);} This line of code is executed even though the thread was interrupted, but it did not end up running. System.out.println ("End run ...");}
Run Results section:
When T gets CPU execution, the If judgment detects the interrupt state, which is called t.interrupt () in the main thread, and the For loop executes a break out of the for loop, but the thread does not end, or continues execution for the statement following the for. You can change the break to return, and the thread ends execution immediately.
Of course, you can also throw interruptedexception exceptions:
Class MyThread1 extends Thread {@Overridepublic void run () {try {for (int i = 1; i < 500000; i++) {if (thread.interrupt Ed ()) {System.out.println ("Stop and Exit ..."); throw new Interruptedexception ();} System.out.println ("I:" + i);} System.out.println ("End run ..."); catch (Exception e) {System.out.println ("catch interrupted ...");}}
When an interrupt is detected as true, an exception is thrown so that the thread no longer executes other normal statements.
Previously said cannot eat interrupt, modify as follows:
Class MyThread1 extends Thread {@Overridepublic void run () {try {for (int i = 1; i < 500000; i++) {if (thread.interrupt Ed ()) {System.out.println ("Stop and Exit ..."); throw new Interruptedexception ();} System.out.println ("I:" + i);} System.out.println ("End run ..."); catch (Exception e) {System.out.println ("catch interrupted ..."); Thread.CurrentThread (). interrupt (); No Eat Interrupts}}}
In this way, the anomaly is further spread by the eat anomaly.
Example 2
Package Com.huawei.thread;public class Test28 extends thread {volatile Boolean stop = false;public static void Main (String [] args) throws interruptedexception {Test28 t = new Test28 (); SYSTEM.OUT.PRINTLN ("Starting thread ..."); T.start (); Thread.Sleep (3000); SYSTEM.OUT.PRINTLN ("Asking Thread to stop ..."); Must be set before interrupt//If the thread is blocked, this variable will not be checked, and after calling interrupt, the thread will be able to check this variable t.stop = True as soon as the end of the blocked state; If the thread is not blocked, calling interrupt will not work. What this method actually accomplishes is that a interrupt signal is thrown when the thread is blocked, so that the threads can exit the blocking state t.interrupt (); Thread.Sleep (3000); System.out.println ("Stopping app ..."); @Overridepublic void Run () {while (!stop) {System.out.println ("running ..."); try {thread.sleep (2000);} catch (Interruptedexception e) {System.out.println ("interrupted ...");}} SYSTEM.OUT.PRINTLN ("Thread exit ...");}}
Take a few points: the stop variable, sleep (), interrupt (), interruptedexception in the Run method. This is what it means to be strung up:
- When we call sleep (or other methods of blocking threads) in the Run method, if the thread is blocked for too long, such as 10s, then within this 10s, the thread is blocked and the Run method is not executed;
- However, if the stop is set to true in this 10s, it indicates that the thread is to be terminated, but now that the thread is blocked, its run method cannot be executed and the stop cannot be checked, so the thread cannot be terminated;
- At this point we can use the interrupt () method: We call the Thread.Interrupt () method after thread.stop = True; The method throws a break signal when the thread is blocked, and the signal is captured by a catch statement. Once this signal is captured, the thread prematurely ends its blocking state;
- This allows it to run the Run method again, and then checks that the stop = True,while loop will no longer be executed, after the Run method executes and the thread terminates after performing the cleanup work behind the while.
When you need to throw a interruptedexception in the code call, you can choose to break the state reset, or you can opt to throw the interruptedexception out, determined by the caller of the outer layer.
Resources
Https://www.ibm.com/developerworks/cn/java/j-jtp05236.html
Http://www.cnblogs.com/hapjin/p/5450779.html
http://blog.csdn.net/canot/article/details/51087772
http://blog.csdn.net/ns_code/article/details/17091267
Http://developer.51cto.com/art/201508/487231.htm
Multithreading-interrupt (), isinterrupted (), Interrupted ()