Concurrency Basics (eight) interrupt mechanism for Java threads

Source: Internet
Author: User
Tags thread class

The article is reproduced from the detailed analysis of the Java interrupt mechanism 1. Introduction

When we click on the Cancel button of an antivirus to stop the virus, when we hit the QUIT command in the console to end a background service ... Requires one thread to cancel the task that another thread is performing. Java does not provide a safe and straightforward way to stop a thread, but Java provides an interrupt mechanism.

If you do not have a thorough understanding of the Java interrupts, you may mistakenly assume that the interrupted thread will exit immediately, but that is not the case. How does the interrupt mechanism work? What happens if the interrupt is caught or detected, is the InterruptedException interrupt state thrown or reset, and the interrupt state is swallowed in the method? Thread.stopwhat are the similarities and differences compared to interrupts? What is the use of interrupts? This article will be described in the above aspects.

2. The principle of interruption

The Java interrupt mechanism is a collaborative mechanism, meaning that the interrupt does not directly terminate the other thread, and the thread that needs to be interrupted handles the interrupt itself. This is like the parents of the family told outside children to pay attention to the body, but whether children pay attention to the body, how to pay attention to the body is entirely dependent on themselves.

The Java interrupt model is also so simple that each thread object has a Boolean identifier (not necessarily the field of the thread class, which is actually not, and these methods are ultimately done by the native method), Represents whether there is an interrupt request (the request can come from all threads, including the thread itself being interrupted). For example, when a thread T1 wants to break thread T2, it only needs to set the interrupt identifier of the thread T2 object to True in the threads T1, then thread 2 can choose to handle the interrupt request at the appropriate time, or even ignore the request, as if the thread had not been interrupted.

The Java.lang.Thread class provides several ways to manipulate this interrupt state, including the following:

Method Method Description
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 if 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.

Where the interrupt method is the only way to set the interrupt state to true. The static method interrupted clears the interrupt state of the current thread, but the method is very straightforward to name, which can easily cause misunderstandings and require special attention.

In the above example, the thread T1 the interrupt state of the thread T2 by calling the interrupt method True,t2 can call interrupted or isinterrupted at the appropriate time to detect the state and do the appropriate processing.

In addition, the methods of some classes in the class library may also call interrupts, such as FutureTask the cancel method in, if the passed parameter is true, it will call the interrupt method on the thread that is running the asynchronous task, if the code in the asynchronous task being executed does not respond to the interrupt, The arguments in the Cancel method will not have any effect, and ThreadPoolExecuto the method in R will shutdownNow traverse the worker thread in the thread pool and call the thread's interrupt method to break thread, so if the task being performed in the worker thread does not respond to the interrupt, The task will be executed until the normal end.

3. Processing of interrupts

Since the Java interrupt mechanism simply sets the interrupt state of the interrupted thread, what should be done by the interrupted thread?

Processing time

Obviously, as a collaboration mechanism, the interrupted thread must not be forced to be processed at a certain point. In fact, the interrupted thread only needs to be processed at the right time, and if there are no suitable points of point, or even no processing, at the task-handling level, it will be the same as no interrupt method. "At the right time" is closely related to the line is impersonating in the business logic that is being processed, for example, every iteration, before entering a potentially blocking and interruptible method, but most of the time it does not appear to update another object state in a critical section, as this may cause the object to be in an inconsistent state.

The processing time determines the efficiency of the program and the agility of the interrupt response. Frequent checking of the interrupt State may reduce program execution efficiency, whereas fewer checks may cause the interrupt request to not respond in a timely manner. If an interrupt request is made and the interrupted thread continues to perform for a period of time without causing the system to be catastrophic, then the interrupt processing can be placed in a convenient way to check for interruptions while at the same time guaranteeing a certain degree of responsiveness. When the performance metrics of your program are critical, you may need to establish a test model to analyze the best interrupt detection points to balance performance and responsiveness.

Processing mode

3.1. Management of interrupt status

In general, when a potentially blocked method declaration has a thrown interruptedexception, it implies that the method is interruptible, such as Blockingqueue#put, Blockingqueue#take, object#wait, thread# Sleep, and so on, if the program captures the interruptedexception that are thrown by these interruptible blocking methods or detects an interrupt, what should these interrupt messages do? There are generally the following two general principles:

If you encounter an interruptible blocking method that throws Interruptedexception, you can continue to throw the exception to the upper layer of the method call stack, and if an interrupt is detected, you can clear the interrupt state and throw interruptedexception. Makes the current method also an interruptible method.
If sometimes it is inconvenient to throw interruptedexception on the method, for example, the method signature on an interface to be implemented does not have throws interruptedexception on it, You can then capture the interruptedexception of the Interruptible method and reset the interrupt state through Thread.currentThread.interrupt (). This is true if the interrupt state is detected and cleared.
In general code, especially as a base class library, you should never swallow interrupts, that is, after capturing to Interruptedexception, do nothing in the catch, clear the interrupt state without resetting the interrupt state or throw interruptedexception and so on. Because swallowing the interrupt state causes the upper layer of the method call stack to get no such information.

Of course, there are always exceptions to this, when you know exactly who your method will be called, and the caller will not get into trouble because the interruption is swallowed up.

It's all about getting the upper layer of the method call stack to learn about the break. Suppose you write a class library that has a method Amethod in the class library, detects and clears the interrupt state in Amethod, and does not throw the interruptedexception, as the Amethod user, he does not know the details, If the user is going to use interrupts to do something after calling Amethod, he will never detect an interruption after calling Amethod, because the interrupt information has been removed by Amethod. What if, as a user, you encounter such a problematic class library and cannot modify the code? I had to set a state of my own in my class, and when I called the interrupt method, I set the state at the same time, which is a way to use it without a way.

3.2. Interrupt response

What should I do when I find an interrupt in the program? This depends on the actual situation. Some programs may terminate a thread as soon as an interrupt is detected, some may exit the currently executing task, and proceed to the next task ... As a collaborative mechanism, this should be negotiated with the interrupt party, and what happens when a call to interrupt is known beforehand, such as doing some transaction rollback operations, some cleanup work, some compensation operations, and so on. If you are not sure what kind of response the thread will respond to after calling the interrupt of a thread, you should not break the thread.

3.3. Thread.Interrupt VS Thread.stop

The Thread.stop method has not been recommended for use. In some respects, thread.stop is similar to the interrupt mechanism. If the thread waits for a built-in lock or IO, stop will not abort these operations, as is the case with interrupt, and the program can continue to execute when the catch stops causing the exception, although stop is intended to stop the thread, and doing so will make the program's behavior more confusing.

So where are the differences? The most important is that the interrupt requires the program to detect and then do the corresponding processing, and Thread.stop will directly in the code execution process to throw Threaddeath error, which is a java.lang.Error subclass.

Before proceeding, let's look at a small example:

Package Com.ticmy.interrupt;import java.util.Arrays;import Java.util.Random;import Java.util.concurrent.TimeUnit; Public classTeststop {Private Static Final int[] Array =New int[80000];Private Static FinalThread T =NewThread () { Public void Run() {Try{System. out.println(Sort(array)); }Catch(Error Err) {Err.Printstacktrace(); } System. out.println("in thread T"); }    };Static{Random random =NewRandom (); for(inti =0; I < array.length; i++) {Array[i] = random.Nextint(i +1); }    }Private Static int Sort(int[] array) { for(inti =0; I < array.length-1; i++) { for(intj =0; J < Array.lengthI1; J + +) {if(Array[j] < Array[j +1]){inttemp = Array[j]; ARRAY[J] = array[j +1]; Array[j +1] = temp; }            }        }returnarray[0]; } Public Static void Main(string[] args)throwsException {T.Start(); Timeunit.SECONDS.Sleep(1); System. out.println("Go to stop thread T"); T.Stop(); System. out.println("Finish Main"); }}

This example is very simple, the thread t inside a very time-consuming sort operation, the sorting method, only simple addition, subtraction, assignment, comparison and other operations, a possible execution result is as follows:

Go to stop thread t
Java.lang.ThreadDeath
At Java.lang.Thread.stop (thread.java:758)
At Com.ticmy.interrupt.TestStop.main (teststop.java:44)
Finish Main
In thread t

Here the sort method is a very time-consuming operation, which means that thread t is still executing the sort method when the main thread sleeps for a second and calls stop. This is an easy way to throw an error! In other words, after the call to stop, most Java bytecode can throw an error, even if it is a simple addition!

If the thread is currently holding a lock, the lock is freed after the stop. Since this error can occur in many places, it is very easy for programmers to avoid the inconsistency of object state. For example, the object obj holds a range value: Minimum low, maximum value high, and low must not be greater than high, which is protected by lock lock to avoid a race condition when concurrency causes the relationship to become invalid. Assuming that the current low value is the 5,high value is 10, when the thread T acquires the lock, the low value is updated to 15, it is stopped at this time, it is really bad, if not capturing the value of stop caused by the error,low is 15,high or 10, This leads to a less than guaranteed relationship between them, which means that the object state is destroyed! If you catch the error when you assign a value to low, it may cause the assignment of the later high variable to continue, but no one knows which statement the error will throw, and if the relationship between the object states is more complex? This approach is almost impossible to maintain, too complicated! If it is an interrupt operation, it does not raise the error when the low assignment is performed, so that the program is controllable for object state consistency.

Stop is disabled because it can cause inconsistent object state.

3.5. Use of interrupts

In general, the usage scenarios for interrupts are as follows:

    • When you click the Cancel button in a desktop app;
    • An operation exceeds a certain execution time limit when it needs to be aborted;
    • Multiple threads do the same thing, as long as a thread succeeds when other threads can be canceled;
    • When one or more errors in a group of threads cause an entire group to fail to continue;
    • When an app or service needs to stop.

Let's look at a specific example. In this example, the intention is to use the GUI form, but given that the GUI code complicates the program, it uses the console to emulate the core logic. This creates a new disk file Scan task, scans all files in a directory and prints the file path to the console, and the scanning process can be lengthy. If you need to abort the task, simply type quit in the console and enter.

Package Com.ticmy.interrupt;import Java.io.BufferedReader;import Java.io.File;import Java.io.InputStreamReader; Public classFilescanner {Private Static void ListFile(File f)throwsinterruptedexception {if(f = =NULL) {Throw NewIllegalArgumentException (); }if(F.Isfile()) {System. out.println(f);return; } file[] Allfiles = f.Listfiles();if(Thread.interrupted()) {Throw NewInterruptedexception ("File Scan task interrupted"); } for(File file:allfiles) {//You can also put interrupt detection here            ListFile(file); }    } Public StaticStringReadfromconsole() {BufferedReader reader =NewBufferedReader (NewInputStreamReader (System.inch));Try{returnReader.ReadLine(); }Catch(Exception e) {e.Printstacktrace();return ""; }    } Public Static void Main(string[] args)throwsException {FinalThread Fileiteratorthread =NewThread () { Public void Run() {Try{ListFile(NewFile ("C:\\")); }Catch(Interruptedexception e) {e.Printstacktrace(); }            }        };NewThread () { Public void Run() { while(true) {if("Quit".Equalsignorecase(Readfromconsole())) {if(Fileiteratorthread.isAlive()) {Fileiteratorthread.Interrupt();return; }                    }Else{System. out.println("Enter quit to exit file Scan"); }                }            }        }.Start(); Fileiteratorthread.Start(); }}

In the process of scanning the file, the policy used here is that if you encounter a file is not detected interrupt, is the directory to detect the interruption, because the file may be very many, each time a file is detected will reduce program execution efficiency. In addition, in the Fileiteratorthread thread, only the interruptedexception is captured, no interrupt state is reset, and no continuation exception is thrown because I am very aware of its usage environment, The top of the call stack for the Run method is no longer likely to require a method to detect the interrupt state.

In this program, input quit can perform system.exit (0) operation to exit the program, but as mentioned earlier, this is a simulation of the GUI program core logic, in the GUI, the execution of System.exit (0) will cause the whole program to exit.

Concurrency Basics (eight) interrupt mechanism for Java threads

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.