The interrupt mechanism of Thread (interrupt)

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Interrupt threads

Thread thread.interrupt () method is interrupted thread, the thread will set the interrupt status, which is set to true, the result of the death, interrupt thread is still waiting for the new task or goes on to the next step, depending on the program itself. Thread will continue to test the interrupt flag bit, to determine whether the thread should be interrupt (interrupt mark if the value is true). It doesn't look like the stop method that would interrupt a running thread.

Judge whether the thread is interrupted

To judge whether or not a thread has been sent through the interrupt request, Please use Thread.currentThread ().IsInterrupted () method (because it will interrupt flag bit is set as the thread true, Not immediately clear interrupt flag bit, That will not interrupt calibration set to false), Instead of using the thread.interrupted () (the method call will interrupt flag bit is cleared, Is re set to false) method to determine, Below is the thread interrupt mode in the cycle time:

while(!Thread.currentThread().isInterrupted() && more work to do){
    do more work
}

How to break the thread

If a thread is in the blocking state (such as thread calls the I/O method of operation thread.sleep, thread.join, thread.wait, condition.await, and 1.5 in the channel can be interrupted by entering the blocking state), In the thread in the check interrupt mark when interrupt labeled true, Is in the blocking method (I/O method of sleep, join, wait, 1.5 condition.await and channel can interrupt the caller throws a InterruptedException exception), And throw an exception immediately after the interrupt flag bit clear thread, Is re set to false. Exceptions to the thread from blocking state to wake up, and at the end of the thread before allowing the programmer to have enough time to handle the interrupt request.

Note, synchronized is not interrupted in the process by the lock, the idea is that if the deadlock, it is not possible to be interrupted (please refer to the back of the test examples). Similar to the synchronized function of the reentrantLock.lock () method is the same, it can not be interrupted, i.e. if deadlock occurs, then the reentrantLock.lock () method cannot be terminated, if be a blocking call, it blocks until it gets to the lock until the. But if a call with reentrantLock.tryLock tryLock timeout(long timeout, TimeUnit unit), So if the thread is waiting for the suspended, A InterruptedException exception will be thrown, This is a very useful feature, Because it allows programs to break the deadlock. You can also call reentrantLock.lockInterruptibly () method, it is equivalent to a timeout is set to tryLock for unlimited.

No language requirement of an interrupted thread should be terminated. Interrupt a thread only to cause the thread's attention, the interrupted thread can decide how to deal with the interruption. Some of the threads is very important, that they should not interrupt, but after the thrown exception continue execution after, but more generally, a thread will interrupt as a request to terminate the thread, the run method according to the following form:

Copy code
public void run() {
    try {
        ...
        /*
         * No matter the cycle is called thread occlusion method such as sleep, join, wait, here is the need to add
         * !Thread.currentThread().isInterrupted()Conditions, although after throwing out of the loop, explicit
         * With the case of blocking is redundant, but if the call blocking method without obstruction, it would be more safe, more timely. 
         */
        while (!Thread.currentThread().isInterrupted()&& more work to do) {
            do more work 
        }
    } catch (InterruptedException e) {
        //The thread is interrupted during the wait or sleep
    } finally {
        //Do some cleaning work before the end of the thread
    }
}
Copy code

The above is the while cycle in try block, if the try in the while cycle, because in the catch block to set the interrupt mark, because throws InterruptedException, interrupt flag bit is automatically cleared, at this time should be so:

Copy code
public void run() {
    while (!Thread.currentThread().isInterrupted()&& more work to do) {
        try {
            ...
            sleep(delay);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();//Reset interrupt mark
        }
    }
}
Copy code

The underlying interrupt exception handling

InterruptedException capture abnormal does not handle and not in the underlying code you, will properly, as follows:

Copy code
void mySubTask(){
    ...
    try{
        sleep(delay);
    }catch(InterruptedException e){}//Don't do this.
    ...
}
Copy code

If you don't know how to deal with cast InterruptedException anomaly, then you have the following good suggestion processing:
1, In the catch clause, Call Thread.currentThread.interrupt () to set the interrupt status (because after throwing interrupt mark will be cleared), Let the outside world via the Thread.currentThread (.IsInterrupted) (marked) to decide whether to terminate the thread or continue, This should be done:

Copy code
void mySubTask() {
    ...
    try {
        sleep(delay);
    } catch (InterruptedException e) {
        Thread.currentThread().isInterrupted();
    }
    ...
}
Copy code

2, Or, better practice is, do not use try to capture such exceptions, let the method directly thrown:

void mySubTask() throws InterruptedException {
    ...
    sleep(delay);
    ...
}

Application of interrupt

Use the interrupt signal to interrupt non blocking threads

Interrupt threads the best, the most recommended way is using shared variables (shared, variable) signal, told the thread must stop running tasks. Thread must periodically check the variable, then in order to stop the task. Example2 describes this way:

Copy code
class Example2 extends Thread {
    volatile boolean stop = false;// Thread interrupt signal

    public static void main(String args[]) throws Exception {
        Example2 thread = new Example2();
        System.out.println("Starting thread...");
        thread.start();
        Thread.sleep(3000);
        System.out.println("Asking thread to stop...");
        // Set the interrupt signal
        thread.stop = true;
        Thread.sleep(3000);
        System.out.println("Stopping application...");
    }

    public void run() {
        // Every second check interrupt signal
        while (!stop) {
            System.out.println("Thread is running...");
            long time = System.currentTimeMillis();
            /*
             * Use a while loop simulation sleep method, here don't use sleep, otherwise they will be thrown on the obstruction
             * Abnormal InterruptedException and exit the loop, so that the while detection of stop conditions will not be executed, 
             * Lost meaning. 
             */
            while ((System.currentTimeMillis() - time <1000)) {}
        }
        System.out.println("Thread exiting under request...");
    }
}
Copy code

The use of thread.interrupt (non blocking) interrupt thread

Although Example2 this method requires some coding, but it is not difficult to achieve. At the same time, it give a chance to the necessary cleanup. Here note that needs to be shared variables defined as volatile type or any access to it into synchronous block / method (synchronized blocks/methods). It is common practice to interrupt a non blocking threads, but for non detection of isInterrupted () conditions would be more concise:

Copy code
class Example2 extends Thread {
    public static void main(String args[]) throws Exception {
        Example2 thread = new Example2();
        System.out.println("Starting thread...");
        thread.start();
        Thread.sleep(3000);
        System.out.println("Asking thread to stop...");
        // An interrupt request
        thread.interrupt();
        Thread.sleep(3000);
        System.out.println("Stopping application...");
    }

    public void run() {
        // Every second detection whether the set of interrupt mark
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Thread is running...");
            long time = System.currentTimeMillis();
            // Simulation of sleep using while cycle
            while ((System.currentTimeMillis() - time <1000) ) {
            }
        }
        System.out.println("Thread exiting under request...");
    }
}
Copy code

So far so good! However, when a thread is blocked waiting for some event, what would happen? Of course, if the thread is blocked, it can't check the shared variables, it cannot stop. This will occur in many cases, for example, call Object.wait (), ServerSocket.accept () and DatagramSocket.receive (), to name a few.

They can block the thread forever. Even if a time-out occurs, before the timeout period expires the waiting is not feasible and not appropriate, therefore, to use some mechanism makes the thread earlier exit the blocked state. Here's a look at interrupt the thread blocking technology.

Using thread.interrupt () interrupt blocked thread

Thread.interrupt()Method does not interrupt a running thread. The method actually is completed, set the thread interrupt flag bit, where the thread is blocked (such as sleep, wait, join calls and other places) throws an exception and interrupt InterruptedException, the state will also be cleared, so the thread exits the blocked state. The following is a concrete realization:

Copy code
class Example3 extends Thread {
    public static void main(String args[]) throws Exception {
        Example3 thread = new Example3();
        System.out.println("Starting thread...");
        thread.start();
        Thread.sleep(3000);
        System.out.println("Asking thread to stop...");
        thread.interrupt();// Call waiting signal interruption Volume Set
        Thread.sleep(3000);
        System.out.println("Stopping application...");
    }

    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Thread running...");
            try {
                /*
                 * If the thread is blocked, will not go to check the interrupt signal stop variables, the thread.interrupt()
                 * The blocking thread from blocking the blocking thread throws an exception, to escape from the blocking state, and
                 * The abnormal block corresponding treatment
                 */
                Thread.sleep(1000);// Thread is blocked, if a thread receives the interrupt operation signals an exception is thrown
            } catch (InterruptedException e) {
                System.out.println("Thread interrupted...");
                /*
                 * If the thread in the call Object.wait () method, or the join (), sleep () method
                 * The process is, the interrupt status will be cleared
                 */
                System.out.println(this.isInterrupted());// false

                //Don't interrupt is decided by yourself, if you need to really interrupt threads, you need to set off, if
                //Do not need, do not call
                Thread.currentThread().interrupt();
            }
        }
        System.out.println("Thread exiting under request...");
    }
}
Copy code

Once the Example3 in the Thread.interrupt () is invoked, the thread will receive an exception, then fled the blocking state and determining should stop. Above we can also use shared semaphore to replace Thread.currentThread (.IsInterrupted) (!), but it is better than the simple.

A deadlock state thread cannot be interrupted.

Example4 tried to interrupt the two thread is in a deadlock state, but the two lines have not received any interrupt signal (throw), so the interrupt () method is not to break the deadlock the thread, because the locking position cannot throw an exception:

Copy code
class Example4 extends Thread {
    public static void main(String args[]) throws Exception {
        final Object lock1 = new Object();
        final Object lock2 = new Object();
        Thread thread1 = new Thread() {
            public void run() {
                deathLock(lock1, lock2);
            }
        };
        Thread thread2 = new Thread() {
            public void run() {
                // Attention, here in the exchanged position
                deathLock(lock2, lock1);
            }
        };
        System.out.println("Starting thread...");
        thread1.start();
        thread2.start();
        Thread.sleep(3000);
        System.out.println("Interrupting thread...");
        thread1.interrupt();
        thread2.interrupt();
        Thread.sleep(3000);
        System.out.println("Stopping application...");
    }

    static void deathLock(Object lock1, Object lock2) {
        try {
            synchronized (lock1) {
                Thread.sleep(10);// Not here.
                synchronized (lock2) {// Be locked in here, although the blocking, but will not throw an exception
                    System.out.println(Thread.currentThread());
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}
Copy code

Interruption of I/O operation

However, if the thread is blocked in I/O operation, again how? I/O can block a thread for quite a long time, especially involved in the network application. For example, the server may need to wait for a request (request), or, in response to a network application may be waiting for the remote host.

To achieve thisInterruptibleChannelInterface channel is interruptible: If a thread in the interruptible channels due to call an obstruction I/O Operation(Common operations generally have these: serverSocketChannel. accept(), socketChannel.connect, socketChannel.open, socketChannel.read, socketChannel.write, fileChannel.read, fileChannel.write)In the blocking state, While another thread invokes the interrupt method of the blocking thread, This will cause the channel is closed, And has blocked thread connection will receive ClosedByInterruptException, And set the interrupt status has been blocking a thread. In addition, if you have set the interrupt state of a thread and a blocking I/O operation in the channel increased, the channel will be closed and the thread immediately received ClosedByInterruptException; and still set the interrupt status. If that is the case, the logic of the code and the third example is the same, only the exception is different.

If you are using a channel (channels) (which is introduced in Java 1.4 new I/O API), the blocked thread will get a ClosedByInterruptException exception. But, you might use Java1.0 there is a traditional I/O, but requires more work. In this case, the Thread.interrupt () will not work, because the threads will not withdraw from the blocked state. Example5 describes this behavior. Although interrupt () is invoked, the thread will not withdraw from the blocked state, such as the accept method of the ServerSocket does not throw an exception.

Luckily, the Java platform provides a solution for this situation, the call blocking the thread socket close () method. In this case, If a thread is blocked in an I/O operation, When calling the close method when the socket, The thread will get a SocketException when calling the accept method (SocketException IOException Zi Yichang) anomaly, This with the use of interrupt (InterruptedException) method causes an exception was thrown very similar, (note, If the stream for reading and writing occlusion, The close method call flow was blocked, Don't call, Don't throw the IOExcepiton, How this case interrupt? I think can be converted to a channel to operate flow can be solved, Such as file channel). The following is a concrete realization:

Copy code
class Example6 extends Thread {
    volatile ServerSocket socket;

    public static void main(String args[]) throws Exception {
        Example6 thread = new Example6();
        System.out.println("Starting thread...");
        thread.start();
        Thread.sleep(3000);
        System.out.println("Asking thread to stop...");
        Thread.currentThread().interrupt();// Then call the interrupt method
        thread.socket.close();// Then call the close method
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
        }
        System.out.println("Stopping application...");
    }

    public void run() {
        try {
            socket = new ServerSocket(8888);
        } catch (IOException e) {
            System.out.println("Could not create the socket...");
            return;
        }
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Waiting for connection...");
            try {
                socket.accept();
            } catch (IOException e) {
                System.out.println("accept() failed or interrupted...");
                Thread.currentThread().interrupt();//To set the interrupt flag bit
            }
        }
        System.out.println("Thread exiting under request...");
    }
}
Copy code

---------------------------------------------------------------------------------------------------------------------------------------------------------

A, no language requirements of an interrupted thread should be terminated. Interrupt a thread only to cause the thread's attention, the interrupted thread can decide how to deal with the interruption.

In two, sleep, join operation of the thread, if the called interrupt (), InterruptedException will be thrown, then interrupt flag thread will reset to false from true, because the threads to handle the exception has been re readiness.

Three, do not interrupt operation, including access to the synchronized section and Lock.lock (), inputSteam.read (), call interrupt () for these problems is invalid, because they don't throw interrupt exception. If you fail to get the resources, they will block indefinitely.

For the Lock.lock (), Lock.lockInterruptibly (), can use interruptible lock operation, it can throw interrupt exception. Equivalent to the waiting time of an infinite Lock.tryLock(long time, TimeUnit unit).

For inputStream resources, some (implementation of the interruptibleChannel interface) through the close () method will close the corresponding resources, congestion will be let go.

 

Have a look first, several methods of the Thread class:

public static boolean interrupted To test whether the current thread has been interrupted. The interrupt status thread clearance by the method. In other words, if two consecutive calls to that method, the second call will return false.

public boolean isInterrupted()

Test whether the thread has been interrupted. Thread state is not affected by the interruption of the method.

public void interrupt()

Interrupt threads.

Lists several methods and related to the interruption and behavior, can see interrupt is interrupted thread. If you do not understand the interrupt mechanism of Java, such an interpretation is easy to cause misunderstanding, that calls the interrupt method will interrupt thread thread.

In fact, the Java interrupt is a cooperation mechanism. That is to say the interrupt method calls the thread object does not necessarily have to interrupt a running thread, it only requires their own thread break at the right time. Each thread has the interrupt status of a Boolean (the state is not in the Thread attribute), interrupt method is just the state set to true.

As for the normal operation of the thread calls interrupt () and can't stop him, only to change the interrupt identifier.

Generally speaking, If a method declaration throw InterruptedException, Said the method is interruptible, such as wait,sleep,join, That is to say the interruptible method will respond to the call to interrupt (for example sleep response interrupt operations include clear interrupt status, Throw InterruptedException), exception is thrown interruptible method, Not directly by the interrupt method directly caused by.

Object.wait, The Thread.sleep method, continuously polling monitoring interrupted flag, that is set to true, will stop blocking and throws a InterruptedException exception.

--------------------------------------------------------------------------------------------------------------------------------------------------------------

See the above description, the Java interrupt is definitely, but I want to know is blocking the thread is how to use the Interuppt method to complete the stop block and throw interruptedException, which depends on interuppt0 Thread native.

The first step in learning Java JNI calls the Native method.

The second step is to download the openjdk source code, find the directory structure in the openjdk-src\jdk\src\share\native\java\lang\Thread.c file.

Copy code
#include "jni.h"
#include "jvm.h"

#include "java_lang_Thread.h"

#define THD "Ljava/lang/Thread;"
#define OBJ "Ljava/lang/Object;"
#define STE "Ljava/lang/StackTraceElement;"

#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))

static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
};

#undef THD
#undef OBJ
#undef STE

JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
Copy code

Still do not understand, some basic first to learn about C.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Allison at August 03, 2014 - 8:20 PM