End of Java thread-interrupt

Source: Internet
Author: User
Tags thread class

End of Java thread--interrupt

Cancel/Close the scene

We know that after starting a thread through the start method of the thread, the thread starts executing the Run method, and the thread exits after the Run method runs, so why do you need to end a thread? There are a number of situations, such as:
Many threads run in a dead loop, such as in producer/consumer mode, where the consumer body is a dead loop, it constantly receives tasks from the queue, performs tasks, and when the program is stopped, we need an "elegant" way to close the thread.
In some graphical user interface programs, threads are user-initiated and perform tasks such as downloading a file from a remote server, which users may want to cancel during the download process.
In some scenarios, such as querying a result from a third-party server, we want to get the results within a limited time, and if not, we want to cancel the task.
Sometimes, we start multiple threads to do the same thing, like a train ticket, we may have multiple friends help to buy train tickets from multiple channels, as long as there is a channel to buy, we will notify the cancellation of other channels.

cancellation/shutdown mechanism
The Java thread class defines the following methods:
Public final void Stop ()

This method looks like it can stop the thread, but this method is flagged in order to be obsolete, simply saying that we should not use it and can ignore it.

In Java, the primary mechanism for stopping a thread is interrupts, which is not forcing the termination of a thread, it is a collaborative mechanism that passes a cancellation signal to the thread, but it is up to the thread to decide how and when to exit, and this section is primarily about understanding the interrupt mechanism of Java.

The thread class defines the following methods for interrupts:
public boolean isinterrupted()
public void Interrupt()
public static Boolean interrupted()

These three methods have similar names and are more easily confused. Isinterrupted () and interrupt () are instance methods that call them through the thread object, interrupted () is a static method that actually calls the Thread.CurrentThread () operation of the current thread.

Each thread has a flag bit that indicates whether the thread has been interrupted.
Isinterrupted: Returns whether the interrupt flag bit for the corresponding thread is true.
Interrupted: Returns whether the interrupt flag bit for the current thread is true, but it also has an important side effect of emptying the interrupt flag bit, that is, calling interrupted () twice in a row, the first return is true, and the second is generally false ( Unless another interrupt occurs at the same time).
Interrupt: What does it mean to interrupt the corresponding thread? Let's take a closer note.

Thread-to-interrupt response
The impact of interrupt () on threads is related to the state of the thread and the IO operation in progress, and we first consider the state of the thread primarily:
RUNNABLE: The thread is running or has a running condition just waiting for the operating system to dispatch
waiting/timed_waiting: Thread is waiting for a condition or timeout
BLOCKED: Thread is waiting for lock, attempting to enter synchronization block
NEW/TERMINATED: Thread has not started or has ended

RUNNABLE
If the thread is running, and no IO operation is performed,interrupt () simply sets the thread's interrupt flag bit and has no other effect . The thread should check the interrupt flag bit at the appropriate location during the run, for example, if the principal code is a loop, it can be checked at the beginning of the loop, as shown here:

Publicclass interruptrunnabledemo extends thread { @Override public void run () { while (! Thread.CurrentThread (). isinterrupted ()) {//... Single Cycle Code} SYSTEM.OUT.PRINTLN ( "Done");} public static void main (string[] args) throws interruptedexception {thread thread = new Interruptrunnabledemo (); Thread.Start (); Thread.Sleep (1000); Thread.Interrupt ();}}        
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

waiting/timed_waiting
The thread performs the following methods to enter the waiting state:
Public final void join() throws Interruptedexception
Public final void wait() throws Interruptedexception

Perform the following methods to enter the Timed_waiting state:
Public final native void wait (long timeout) throws interruptedexception;
public static native void sleep (long Millis) throws interruptedexception;
Public final synchronized void join (long Millis) throws Interruptedexception

In these states, calling interrupt () on the thread object causes the thread to throw interruptedexception, and it is important to note that the interrupt flag bit is emptied instead of being set when an exception is thrown. For example, execute the following code:

new Thread (){    @Override    public void run() {        try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println(isInterrupted()); } } };t.start();try { Thread.sleep(100);} catch (InterruptedException e) {}t.interrupt();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

The output of the program is false.

Interruptedexception is a checked exception and the thread must handle it. We have explained in exception handling that the basic idea of dealing with exceptions is that if you know how to handle it, you handle it, and if you don't know it, you should pass it up, usually you shouldn't do that, catch the exception and then ignore it.

Capturing to interruptedexception, which usually means that you want to end the thread, has about two ways of handling the thread:
The exception is passed up, which makes the method an interruptible method that needs to be handled by the caller.
In some cases, can not pass the exception, such as the thread of the Run method, its declaration is fixed, can not throw any of the abnormal, at this time, should catch the exception, the appropriate cleanup operation, after cleaning, generally should call the thread's interrupt method to set the interrupt flag bit, Makes it possible for other code to know that it has been interrupted.

The example code for the first way is as follows:

public void interruptibleMethod() throws InterruptedException{    ... 包含wait, join 或 sleep 方法    Thread.sleep(1000);}
    • 1
    • 2
    • 3
    • 4

The second way of the sample code is as follows:

PublicClassInterruptwaitingdemoExtendsThread {@OverridePublicvoidRun () {while (! Thread.CurrentThread (). isinterrupted ()) { try { //Simulate Task code Thread.Sleep (2000);} catch (Interruptedexception e) { //... Cleanup operation //Reset interrupt flag bit Thread.CurrentThread (). interrupt ();}} System.out.println (isinterrupted ()); } public static void main (string[] args) {Interruptwaitingdemo thread = new Interruptwaitingdemo ( ); Thread.Start (); try {thread.sleep (100);} catch (Interruptedexception e) {} thread.interrupt ();}}          
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26

BLOCKED
If the thread is waiting for a lock, calling interrupt () on the thread object simply sets the thread's interrupt flag bit, and the thread remains in the blocked state , that is,interrupt () does not allow a thread waiting for the lock to actually "break" . Let's look at the section code:

PublicClassInterruptsynchronizeddemo {PrivateStatic Object lock =New Object ();PrivateStaticClassAExtendsThread {@Overridepublic void run () {synchronized (lock) {while (! Thread.CurrentThread (). isinterrupted ()) {}} System.out.println ( "exit");}} public static void test () throws interruptedexception { Synchronized (lock) {A A = new A (); A.start (); Thread.Sleep (1000); A.interrupt (); A.join ();}} public static void main (string[] args) throws interruptedexception {Test ();}}    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

The test method starts thread a while holding lock locks, and thread A also attempts to acquire lock locks, so it enters the lock waiting queue, then test calls thread A's interrupt method and waits for thread A to end, thread a ends? No, the interrupt method only sets the interrupt flag for the thread, and does not make it come out of the lock waiting queue.

We change the code slightly, removing the last line in the test method A.join, which becomes:

public static void test() throws InterruptedException { synchronized (lock) { A a = new A(); a.start(); Thread.sleep(1000); a.interrupt(); }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

At this point, the program exits. Why is it? Because the main thread no longer waits for thread A to end, when the lock lock is released, thread a obtains the lock, and then detects that an interrupt occurred, so it exits.

The limitation of synchronized is that it does not respond to interrupt requests in the process of acquiring a lock using the Synchronized keyword. If this is a problem with the program, an explicit lock should be used, and we'll cover the explicit lock lock interface later in this section, which supports acquiring locks in response to interrupts.

NEW/TERMINATE
If the thread has not started (NEW) or has ended (TERMINATED), calling interrupt () has no effect on it, and the interrupt flag bit is not set. For example, the output of the following code is false.

PublicClassInterruptnotalivedemo {PrivateStaticClassa extends Thread { @Override public void run () {}} public static void test () throws interruptedexception {A A = new A (); A.interrupt (); System.out.println (a.isinterrupted ()); A.start (); Thread.Sleep (100); A.interrupt (); System.out.println (a.isinterrupted ()); } public static void main (string[] args) throws interruptedexception {Test ();}}    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22

IO Operation
If the thread is waiting for IO operation, especially network IO, there will be some special processing, we have not introduced the network, here is just a brief introduction.
If the IO channel is interruptible, that is, the Interruptiblechannel interface is implemented, the interrupt flag bit of the thread is set and the thread receives an exception closedbyinterruptexception.
If a thread is blocked by a selector call, the interrupt flag bit for the thread is set, and the blocked call returns immediately.

We highlight another case where InputStream's read call, which is non-interruptible, is blocked if there is no data in the stream (but the thread state remains runnable) and does not respond to interrupt (), similar to synchronized Calling interrupt () only sets the interrupt flag for the thread and does not really "break" it, we look at the segment code.

PublicClassInterruptreaddemo {PrivateStaticclass a extends thread { @Override public void run () {while (! Thread.CurrentThread (). isinterrupted ()) {try {System.out.println (System.in.read ());} Span class= "Hljs-keyword" >catch (IOException e) {e.printstacktrace ();}} System.out.println ( "exit");}} public static void main (string[] args) throws interruptedexception {A t = new A (); T.start (); Thread.Sleep (100); T.interrupt ();}}          
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23

After thread T is started, call System.in.read () to read a character from the standard input, do not enter any characters, and we will see that calling interrupt () will not interrupt read () and the thread will run.

However, there is one way to interrupt the read () call, which is the Close method of the call flow, and we change the code to:

PublicClassInterruptreaddemo {PrivateStaticClassAExtendsThread {@OverridePublicvoidrun () {while (! Thread.CurrentThread (). isinterrupted ()) {try {System.out.println (System.in.read ());} Span class= "Hljs-keyword" >catch (IOException e) {e.printstacktrace ();}} System.out.println ( "exit");} public void cancel () {try {System.in.close ();} catch (IOException e) {} interrupt ();} } public static void main (string[] args) throws interruptedexception {A t = new A (); T.start (); Thread.Sleep (100); T.cancel ();}}         
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

We define a cancel method for the thread, in which the Close method of the stream is called, and the interrupt method is called, and this time the program outputs:

-1exit
    • 1
    • 2

That is, after the Close method is called, the Read method returns with a return value of-1, which indicates that the stream ends.

How to properly cancel/close a thread

There are three ways to make a terminating thread.

1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。 2.  使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。 3.  使用interrupt方法中断线程。

Above, we can see that the interrupt method does not necessarily really "break" the thread, it is just a collaboration mechanism, if you do not understand what the thread is doing, should not rashly call the thread of the interrupt method, thinking that it can cancel the thread.

For a program module that serves as a thread, it should encapsulate the cancel/close operation and provide a separate cancellation/shutdown method to the caller, similar to the Cancel method demonstrated in Interruptreaddemo, where external callers should call these methods instead of calling interrupt directly.

Some code for the Java Concurrency Library provides a separate cancellation/shutdown method, for example, the future interface provides the following methods to cancel a task:
Boolean Cancel (Boolean mayinterruptifrunning);

For example, Executorservice provides the following two methods of closing:
void shutdown ();
List Shutdownnow ();

These methods are described in detail in the future and Executorservice API documentation, which is the way we should learn. For these two interfaces, we introduce the following chapters.

Summary
This section mainly describes how to cancel/close a thread in Java, the main reliance on the technology is interrupt, but it is a collaborative mechanism, does not force the termination of the thread, we describe the thread in different states and IO operations on the interrupt response, as the thread's implementation, should provide an explicit cancellation/shutdown method, And the document describes its behavior, as the caller of the thread, should use its Cancel/Close method instead of calling interrupt hastily.

End of Java thread-interrupt

Related Article

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.