One, the phenomenon of Java interruption
First, look at some of the methods in the thread class:
| public static Boolean interrupted |
Test if the front thread has been interrupted. The interrupt state of the thread is purged by this method. In other words, if the method is called twice in a row, the second call will return False (except in the case where the current thread is interrupted again until the first call has cleared its break state and the second call has finished verifying the break state). |
| public boolean isinterrupted() |
Tests whether the thread has been interrupted. The interrupt state of the thread is not affected by the method. |
| public void Interrupt() |
The thread is disconnected. |
The above lists several methods related to interrupts and their behavior, and you can see that interrupt is a thread break. If you do not understand the interrupt mechanism of Java, such an explanation is very easy to misunderstand, that the interrupt method that invokes the thread must break the thread.
In fact, Java interrupts are a collaborative mechanism. This means that invoking the thread object's interrupt method does not necessarily break the running thread, it simply requires the thread to break itself at the right time. Each thread has a Boolean interrupt state (not necessarily the property of the object, in fact, the state is really not a thread's field), and the interrupt method simply resets the state to True
Copy CodeThe code is as follows:
public class Testinterrupt {
public static void Main (string[] args) {
Thread t = new MyThread ();
T.start ();
T.interrupt ();
System.out.println ("Interrupt method for called threads");
}
Static Class MyThread extends Thread {
public void Run () {
int num = Longtimerunningnoninterruptmethod (2, 0);
System.out.println ("Long time task run end, num=" + num);
SYSTEM.OUT.PRINTLN ("Interrupt State of Thread:" + thread.interrupted ());
}
private static int Longtimerunningnoninterruptmethod (int count, int initnum) {
for (int i=0; i<count; i++) {
for (int j=0; j<integer.max_value; J + +) {
Initnum + +;
}
}
return initnum;
}
}
}
In general, the following is printed:
Interrupt method for called thread
Long time task run end, num=-2
Interrupt status for thread: True
It can be seen that the interrupt method does not necessarily break the thread. But what happens if we change to the following procedure?
Copy CodeThe code is as follows:
Import Java.util.concurrent.TimeUnit;
public class Testinterrupt {
public static void Main (string[] args) {
Thread t = new MyThread ();
T.start ();
T.interrupt ();
System.out.println ("Interrupt method for called threads");
}
Static Class MyThread extends Thread {
public void Run () {
int num =-1;
try {
num = Longtimerunninginterruptmethod (2, 0);
} catch (Interruptedexception e) {
SYSTEM.OUT.PRINTLN ("Thread is Interrupted");
throw new RuntimeException (e);
}
System.out.println ("Long time task run end, num=" + num);
SYSTEM.OUT.PRINTLN ("Interrupt State of Thread:" + thread.interrupted ());
}
private static int Longtimerunninginterruptmethod (int count, int initnum) throws interruptedexception{
for (int i=0; i<count; i++) {
TimeUnit.SECONDS.sleep (5);
}
return initnum;
}
}
}
After the operation can be found that the program throws an exception stopped, the Run method of the latter two print statements are not executed. So, where is the difference?
In general, if a method declaration throws a interruptedexception, it means that the method is interruptible (except when the interrupt is not handled in the method and the Interruptedexception is declared). That is, the Interruptible method responds to the interrupt call (for example, the operation of the sleep response interrupt includes clearing the interrupt state, throwing the interruptedexception), if the interrupt call was made before the Interruptible method, Interruptible methods are bound to handle interrupts, as in the above example, the interrupt method is most likely called when run does not enter sleep, but when sleep detects an interrupt, the interrupt is processed. What happens if you call interrupt while the Interruptible method is executing? This depends on the time the Interruptible method deals with interrupts, as long as the Interruptible method can detect that the interrupt status is true. Let's add interrupt handling to the code at the beginning.
So how can a custom interruptible method handle interrupts? That is to detect the interrupt state of the thread and handle it where it is appropriate to handle interrupts.
Copy CodeThe code is as follows:
public class Testinterrupt {
public static void Main (string[] args) throws Exception {
Thread t = new MyThread ();
T.start ();
TimeUnit.SECONDS.sleep (1);//If you cannot see the interruption during processing, you can enable this sentence and look at the effect
T.interrupt ();
System.out.println ("Interrupt method for called threads");
}
Static Class MyThread extends Thread {
public void Run () {
int num;
try {
num = Longtimerunningnoninterruptmethod (2, 0);
} catch (Interruptedexception e) {
throw new RuntimeException (e);
}
System.out.println ("Long time task run end, num=" + num);
SYSTEM.OUT.PRINTLN ("Interrupt State of Thread:" + thread.interrupted ());
}
private static int Longtimerunningnoninterruptmethod (int count, int initnum) throws Interruptedexception {
if (interrupted ()) {
throw new Interruptedexception ("the formal processing of the front-line has been interrupted by request");
}
for (int i=0; i<count; i++) {
for (int j=0; j<integer.max_value; J + +) {
Initnum + +;
}
If this is the right place
if (interrupted ()) {
Rollback data, cleanup operations, etc.
throw new Interruptedexception ("line is impersonating is interrupted during processing");
}
}
return initnum;
}
}
}
As in the above code, method Longtimerunningmethod is now an interruptible method. When entering the method to determine whether the request is interrupted, if so, do not do the appropriate processing, the process, there may be a suitable place to deal with the interruption, such as the top of the above loop after the end.
This code detects interrupts using the thread's static method interrupted, which resets the interrupt state to false and returns the previous state, while isinterrupted only detects interrupts and does not change the interrupt state. In general, the interrupt request has been processed and its status should be set to false. But it depends on the actual situation.
second, the nature of the Java interrupt
Historically, Java has tried to provide preemptive throttling interrupts, but there are many problems, such as obsolete thread.stop, Thread.Suspend, and Thread.Resume. On the other hand, due to the robustness of Java application code, it reduces the programming threshold and reduces the probability that programmers who do not know the underlying mechanism unintentionally destroy the system.
Today, thread scheduling in Java does not provide preemptive interrupts, but employs collaborative interrupts. In fact, the cooperative interruption, the principle is very simple, is to poll a token that represents the interruption, we can be implemented in any ordinary code. For example, the following code:
Copy CodeThe code is as follows:
volatile bool isinterrupted;
...
while (!isinterrupted) {
Compute ();
}
However, the above code problem is also obvious. When the compute execution time is longer, the interrupt cannot be responded to in time. On the other hand, using polling to check flag variables means that you do not want to interrupt a thread blocking operation such as wait and sleep.
If you still use the idea above, you must check the tag variables at the bottom of the virtual machine if you want the interrupt to be answered in time. Yes, that's exactly what the JVM does. The following excerpt from the source code of Java.lang.Thread:
Copy CodeThe code is as follows:
public static Boolean interrupted () {
Return CurrentThread (). isinterrupted (True);
}
...
Private Native Boolean isinterrupted (Boolean clearinterrupted);
It can be found that isinterrupted is declared as the native method, depending on the implementation of the JVM's underlying.
In fact, the internal JVM does maintain an interrupt token for each thread. However, the application cannot directly access this interrupt variable and must be manipulated in the following ways:
Copy CodeThe code is as follows:
public class Thread {
Set Interrupt Flag
public void interrupt () {...}
Gets the value of the interrupt token
public Boolean isinterrupted () {...}
Clears the interrupt token and returns the value of the last interrupt token
public static Boolean interrupted () {...}
...
}
Normally, calling the thread's interrupt method does not immediately cause an interrupt, but only sets the interrupt token inside the JVM. Therefore, by checking the interrupt token, the application can do some special operations, or it can completely ignore interrupts.
You might think that if the JVM only provides this humble interrupt mechanism, it has little advantage over the way the application defines the interrupt variable and polls itself.
The main advantage of a JVM's internal interrupt variable is that it provides a mechanism for simulating automatic "break-in" in some cases.
When executing blocking calls involving thread scheduling (for example, wait, sleep, and join), the blocked thread throws Interruptedexception "as fast as possible" if an interrupt occurs. Therefore, we can use the following code framework to handle thread blocking interrupts:
Copy CodeThe code is as follows:
try {
Wait, sleep, or join
}
catch (Interruptedexception e) {
Some interrupt processing work
}
So-called "as fast as possible", I guess the JVM is the Gap check interrupt variable for the thread dispatch schedule, and the speed depends on the implementation of the JVM and the performance of the hardware.
Three, some thread blocking operations that do not throw interruptedexception
However, for some thread blocking operations, the JVM does not automatically throw interruptedexception exceptions. For example, some I/O operations and internal lock operations. For such operations, you can simulate interrupts in other ways:
1) asynchronous socket I/O in java.io
Read and write methods of InputStream and OutputStream block waiting when reading and writing sockets. It does not respond to Java interrupts. However, when the Close method of the socket is called, the blocked thread throws a SocketException exception.
2) asynchronous I/O implemented with selector
If the thread is blocked in Selector.select (in Java.nio.channels), calling the Wakeup method causes a Closedselectorexception exception.
3) Lock acquisition
If the thread is waiting for an internal lock, we will not be able to break it. However, using the lockinterruptibly method of the lock class, we can provide interrupt capability while waiting for the lock.
Four, two programming principles
In addition, in a task-to-thread-separated framework, a task usually does not know which thread it is calling, and it does not know the policy that invokes the thread to handle the interrupt. Therefore, after the task has set a thread break token, it does not ensure that the task is canceled. Therefore, there are two programming principles:
1) You should not interrupt a thread unless you know the interrupt policy for it.
This principle tells us that you should not call the interrupt method of a frame thread such as executer directly, and you should use methods such as Future.cancel to cancel the task.
2) The task code should not guess what interrupts mean to the thread of execution.
This principle tells us that the general code should not be caught in the interruptedexception exception, but should continue to be thrown into the upper code.
in short, the non-preemptive interrupt mechanism in Java requires that we must change the traditional preemptive interrupt idea, and use the corresponding principles and patterns to program it on the basis of understanding its essence. !--newszw_hzh_end-->
Http://www.jb51.net/article/32359.htm
Http://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java?rq=1
Http://blog.sina.com.cn/s/blog_7a351012010166si.html
Deep understanding of the nature of Java thread interrupts (go)