Explanation of the Java interrupt mechanism

Source: Internet
Author: User

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.

One, the phenomenon of Java interruption
First, look at some of the methods in the thread class:

public static boolean 

P> 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

P>  isinterrupted ()

test whether the thread has been interrupted. The interrupt state of the thread   is not affected by the method.
public void  Interrupt ()


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.
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 indeed not a thread's field), and the interrupt method simply resets the state to true. The code is as follows:

public class Test {
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? The code is as follows:

Ipublic class Test {
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;
}
}
The results of the operation are as follows: interrupt method for called thread
thread is interrupted
Exception in Thread "Thread-0" Java.lang.RuntimeException:java.lang.InterruptedException:sleep interrupted
At Chapter1.test$mythread.run (test.java:20)
caused By:java.lang.InterruptedException:sleep interrupted
At Java.lang.Thread.sleep (Native Method)
At java.lang.Thread.sleep (thread.java:340)
At java.util.concurrent.TimeUnit.sleep (timeunit.java:360)
At Chapter1.test$mythread.longtimerunninginterruptmethod (test.java:29)
At Chapter1.test$mythread.run (test.java:17)

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. The code is as follows:

public class Test {
public static void Main (string[] args) throws Exception {
Thread t = new MyThread ();
T.start ();
TimeUnit.MILLISECONDS.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:

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:

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:

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. The 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, the following two programming principles are available:
1) You should not interrupt a thread unless you know the interrupt policy for it. The principle of
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

An explanation of the Java interrupt mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.