The nature of Java thread interrupts deep understanding _java

Source: Internet
Author: User
first, the phenomenon of Java interruption
First, look at several methods in the thread class:
public static Boolean interrupted Test if the thread has been interrupted. The interrupt state of the thread is cleared by the method. In other words, if the method is called twice in a row, the second call returns FALSE, except if the first call has cleared its break state, and the second call is interrupted before the interrupt state is checked out.
public boolean isinterrupted() Whether the test thread has been interrupted. The interrupt state of a thread is not affected by this method.
public void Interrupt() The thread is disconnected.

The above lists several methods and their behaviors related to interrupts, and you can see that interrupt is a thread in. If you do not understand the Java interrupt mechanism, such an explanation is highly misleading, thinking that the interrupt method that invokes the thread must break the thread.
In fact, Java interrupts are a collaborative mechanism. That is to say, the interrupt method of the calling thread object does not necessarily interrupt the running thread, it simply requires the thread to interrupt itself at the right moment. Each thread has a Boolean interrupt state (not necessarily the object's property, in fact, the state is not a field of thread), and the interrupt method simply resets the state to True
Copy Code code as follows:

public class Testinterrupt {
public static void Main (string[] args) {
Thread t = new mythread ();
T.start ();
T.interrupt ();
System.out.println ("Interrupt method of the invoked thread");
}
Static Class Mythread extends Thread {
public void Run () {
int num = Longtimerunningnoninterruptmethod (2, 0);
System.out.println ("Long time task runs over, 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;
}
}
}

Typically, the following is printed:
Interrupt method for the invoked thread
Long time task run over, num=-2
Interrupt state of Thread: TRUE
It can be seen that the interrupt method does not necessarily interrupt the thread. But what happens if you change to the following procedure?
Copy Code code 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 of the invoked thread");
}
Static Class Mythread extends Thread {
public void Run () {
int num =-1;
try {
num = Longtimerunninginterruptmethod (2, 0);
catch (Interruptedexception e) {
SYSTEM.OUT.PRINTLN ("Thread Interrupted");
throw new RuntimeException (e);
}
System.out.println ("Long time task runs over, 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 running, you can find that the program throws an abnormal stop, and the latter two print statements in the Run method are not executed. So, where's the difference?
In general, if a method declaration throws a interruptedexception, it means that the method is interruptible (except that it does not handle interrupts in the method but also declares that the interruptedexception is thrown). That is, the Interruptible method responds to the interrupt call (for example, the action of the Sleep response interrupt includes clearing the interrupt state, throwing interruptedexception) if the interrupt call was made before the Interruptible method. The Interruptible method will certainly handle interrupts, as in the example above, the interrupt method is most likely invoked when run is not in sleep, but the interrupt is handled by the failure when it detects an interrupt. What happens if you call interrupt when the Interruptible method is executing? This depends on the time the Interruptible method handles the interrupt, so long as the Interruptible method detects that the break state is true, the interrupt should be handled. Let's add interrupt handling for the beginning of the piece of code.
So how does a custom interruptible method handle interrupts? That is to detect the thread interrupt state and handle it where it is appropriate to handle interrupts.
Copy Code code 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 situation that was interrupted during the processing, you can enable this sentence to see the effect
T.interrupt ();
System.out.println ("Interrupt method of the invoked thread");
}
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 runs over, 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 ("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 one thread interrupted during process");
}
}
return initnum;
}
}
}

As the code above, method Longtimerunningmethod is now an interruptible method. When entering the method to determine whether the request is interrupted, if it is, do not deal with the corresponding process, there may also be a suitable place to deal with the interruption, such as the upper most inner loop after the end.
The detection interrupt in this code uses 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. Generally, 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 Java interrupts
Historically, Java has tried to provide preemptive restriction interrupts, but there are many problems, such as Thread.stop, Thread.Suspend, and Thread.Resume, which have been discarded. On the other hand, due to the robustness of Java application code, the threshold of programming is reduced, and the probability that programmers who are not aware of the underlying mechanism is unintentionally destroying the system is reduced.
Today, Java thread scheduling does not provide preemptive interrupts, but uses collaborative interrupts. In fact, the collaborative interruption, the principle is very simple, that is, polling a token to indicate the interruption, we can be implemented in any normal code. For example, the following code:
Copy Code code as follows:

volatile bool isinterrupted;
...
while (!isinterrupted) {
Compute ();
}

However, the above code issues are 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 for flag variables, there is no way to interrupt thread blocking operations such as wait and sleep.
If you still use the above ideas, to allow interrupts to be responded to in a timely manner, you must check the tag variables at the bottom of the virtual machine for thread scheduling. Yes, that's exactly what the JVM does. The following is an excerpt from Java.lang.Thread's source code:
Copy Code code 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 a native method, depending on the implementation of the JVM's underlying.
Indeed, within the JVM, a break tag is indeed maintained for each thread. However, the application cannot access the interrupt variable directly, and you must do so in the following ways:
Copy Code code as follows:

public class Thread {
Set interrupt Marks
public void interrupt () {...}
Gets the value of the interrupt token
public Boolean isinterrupted () {...}
Clears the interrupt mark and returns the value of the last interrupt mark
public static Boolean interrupted () {...}
...
}

Typically, the calling thread's interrupt method does not immediately cause an interrupt, but sets the interrupt tag inside the JVM. Therefore, by checking the interrupt tag, the application can do some special work or completely ignore the interrupt.

You might think that if the JVM only provides this rudimentary interrupt mechanism, it has little advantage over the way the application defines the interrupt variable and polls itself.

The main advantage of the internal interrupt variable in the JVM is that it provides a mechanism for simulating automatic "interrupt falling" in some cases.
When execution involves blocking calls that involve thread scheduling (such as wait, sleep, and join), the blocked thread throws the Interruptedexception "as fast as possible" if an interrupt occurs. Therefore, we can use the following code framework to handle thread blocking interrupts:
Copy Code code as follows:

try {
Wait, sleep, or join
}
catch (Interruptedexception e) {
Some interrupt processing work
}

The so-called "as fast as possible," I guess the JVM is the thread scheduling scheduling gap check interrupt variable, speed depends on the implementation of the JVM and hardware performance.

third, some thread blocking operations that do not throw interruptedexception
However, the JVM does not automatically throw interruptedexception exceptions for some thread blocking operations. For example, some I/O operations and internal lock operations. For this type of operation, you can simulate interrupts in other ways:
1) asynchronous socket I/O in java.io
When reading and writing sockets, the Read and write methods of InputStream and OutputStream block the wait, but do not respond to Java interrupts. However, when the Close method of the socket is invoked, 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), invoking the Wakeup method can cause closedselectorexception exceptions.
3) Lock Acquisition
If the thread is waiting to acquire an internal lock, we will not be able to interrupt 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-and-thread-separated framework, a task usually does not know which thread it will be invoked by, nor does it know the policy of the calling thread to handle the interrupt. Therefore, after the task has set the thread interrupt tag, it is not possible to ensure that the task is canceled. Therefore, the following two programming principles are:
1 unless you know the thread's interrupt strategy, you should not interrupt it.
This principle tells us that we should not directly call the interrupt method of the Executer frame thread, and should use methods such as Future.cancel to cancel the task.

2 The task code should not guess the meaning of the interrupt on the execution thread.
This principle tells us that the general code should not be caught after the interruptedexception exception, but should continue to throw to the upper layer of code.
In a word, the non preemptive interrupt mechanism in Java requires us to change the traditional preemptive interrupt idea, and to use the corresponding principles and patterns to program the basic understanding of its essence.

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.