Interrupting Thread

A thread terminates when its "run" method returns -- by executing a return statement, after executing the last statement in the method body, or if an exception occurs that is not caught in the method. There is no additional way

to force a thread to termiante. However, the "interrupt" method can be used to request termination of a thread.

Whe the "interrupt" method is called on a thread, the "interrupted status" of the thread is set. This is a "boolean" flag

that is present in every thread. Each thread should occasionally check whether it has been interrupted.

To find out wheather the interrupted status was set, first call the static "Thread.currentThread" method to get the current thread, and then call the "isInterrupted" method:

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

However, if a thread is blocked, it cannot check the interrupted status. This is where the "InterruptedException" comes in. When the "interrupt" method is called on a thread that blocks on a call such as "sleep" or "wait", the blocking call

is terminated by an "InterruptedExeption". (There are blocking I/O calls that cannot be interrupted; you should consider interruptible alternatives).

The interrupted thread can decide how to react to the interruption. Some threads are so important that they should handle the exception and continue. But quite commonly, a thread will simply want to interpret an interruption as a request for termination. The "run" method of such a thread has the following form:

Runnable r = () -> {
    try {
        ...
        while (!Thread.currentThread.isInterrupted() && more work to do) {
            do more work
       }
    } catch (InterruptedException e) {
        //thread was interrupted during sleep or wait
    } finally {
        cleanup, if required
    }
    //exiting the run method terminates the thread
};

The "isInterrupted" check is neither necessary nor useful if you call the "sleep" method (or another interruptible method) after every work iteration. If you call the "sleep" method when the interrupted status is set, it doesn't sleep. Instead, it clear the status ! And throws an "InterruptedException". Therefore, if you loop calls "sleep", don't check the interrupted status. Instead, catch the "InterruptedException", like this:

 
 
Runnable r = () -> {
    try {
        ...
        while (more work to do) {
            do more work
            Thread.sleep(delay);   //If the "sleep" method is interrupted, another circulation begins.
                                   //In that case the interrupted status is set when the "sleep" method is interrupted,
                                   //and the "sleep" method call is looped.
        }
    } catch (InterruptedException e) {
        //thread was interrupted during sleep or wait
    } finally {
        cleanup, if required
    }
    //exiting the run method terminates the thread
};

NOTE: There are two very similar methods, "interrupted" and "isInterrupted". The "interrupted" method is a static method that checks wheather the current thread has been interrupted. Furthermore, calling the "interrupted" method clears the interrupted status of the thread. On the other hand, the "isInterrupted" method is an instance method that you can use to check whether any thread has been interrupted. Calling it does not change the interrupted status.

You will find lots of published code in which the InterruptedException is squelched at a low level, like this:

void mySubTask() {

    try {

        sleep(delay);

    } catch(InterrptedException e) {}

    ... ...

}

    Don't do that! If you can't think of anything to do in the "catch" clause, you still have two reansonable choices:

In the "catch" clause, call "Thread.currentThread().interrupt()" to set the interrupted status.

Then the caller can test it:

void mySubTask() {

        try {

            sleep(delay);

        } catch(InterrptedException e) {

            Thread.currentThread().interrupt();

        }

        ... ...

    }

Or, even better, tag your method with "throws InterruptedException" and drop the "try" block.

Then the caller (or, ultimately, the "run" method) can catch it.   

void mySubTask() throws InterruptedException {

        ... ... 

        sleep(delay);

        ... ...

    }


猜你喜欢

转载自blog.csdn.net/liangking81/article/details/80657236