Friday 3 February 2012

interrupt() method in Java Thread

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

Interruption is a cooperative mechanism. When one thread interrupts another, the interrupted thread does not necessarily stop what it is doing immediately. Instead, interruption is a way of politely asking another thread to stop what it is doing if it wants to, at its convenience.

A thread sends an interrupt by invoking interrupt() on the Thread object for the thread to be interrupted.(i.e. t.interrupt(); interrupts the thread t). For the interrupt mechanism to work correctly, the interrupted thread must support its own interruption.

public void interrupt() throws SecurityException 

Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.Let us see the thread interruption in different scenarios.
1) If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, it unblocks and throws InterruptedException.Once throws the exception, thread's interrupt status will be cleared i.e. reset to 'false'.

2) If this thread is blocked in an I/O operation upon an interruptible channel, then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

3) If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

4) If none of the previous conditions hold then this thread's interrupt status will be set.

5) Interrupting a thread that is not alive need not have any effect.

6) The interrupt() method throws SecurityException, if the current thread cannot modify this thread.

7) Attempting to acquire an intrinsic lock (enter a synchronized block) cannot be interrupted, but ReentrantLock supports an interruptible acquisition mode.

The Interrupt Status flag

The interrupt mechanism is implemented using an internal flag known as the interrupt status.The initial value of it is 'false'.

If you interrupt a thread which has been blocked by the invocation of wait,sleep or join ,it will be unblocked and receives an InterruptedException ,then its interrupt status will be cleared(i.e. set interrupt status =false).However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt().
In other scenarios, the interrupt() merely sets the thread's interruption status (i.e. set interrupt status =true).

Retrieve the Interrupt Status
We can retrieve the interrupt status of a thread using the following methods
  • public static boolean interrupted()
  • public boolean isInterrupted()
Let us see the difference between above two methods.

public static boolean interrupted()
Tests whether the current thread has been interrupted and then returns the status.Once return the status,it will clear the interrupt status i.e. set the status as false.In other words, if this method were to be called twice in succession, the second call would return false (unless the current thread were interrupted again, after the first call had cleared its interrupted status and before the second call had examined it).
public boolean isInterrupted()
 
The non-static isInterrupted method, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.

Supporting Interruption

How does a thread support its own interruption? This depends on what it's currently doing. If the thread is frequently invoking methods that throw InterruptedException, it simply returns from the run method after it catches that exception.Consider one example
class MyThread extends Thread {
    public void run() {
        while (true) {
            System.out.println("mythread is running");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                System.out.println("mythread is interrupted");
                return;
            }
        }
    }
}
public class Main {
    public static void main(String args[]) {
        MyThread mythread = new MyThread();
        mythread.start();
        mythread.interrupt();
    }
}

The output is given below (may change depends on processor)

mythread is running
mythread is interrupted

Here the execution returns from run() method after the interruption has occurred.

What if a thread goes a long time without invoking a method that throws InterruptedException? Then it must periodically invoke Thread.interrupted(), which returns true if an interrupt has been received. For example:

class MyThread extends Thread {
    public void run() {
        while (true) {
            System.out.println("mythread is running");
            if(Thread.interrupted())
                System.out.println("mythread is interrupted");
                return;
            }
        }
    }
public class Main {
    public static void main(String args[]) {
        MyThread mythread = new MyThread();
        mythread.start();
        mythread.interrupt();
    }
}

The output is given below (may change depends on processor)

mythread is running
mythread is interrupted

In this simple example, the code simply tests for the interrupt and exits the thread if one has been received. In more complex applications, it might make more sense to throw an InterruptedException:

if (Thread.interrupted()) {
     throw new InterruptedException();
}

This allows interrupt handling code to be centralized in a catch clause.

One of the benefits of the cooperative nature of interruption is that it provides more flexibility for safely constructing cancelable activities. We rarely want an activity to stop immediately; program data structures could be left in an inconsistent state if the activity were canceled mid-update. Interruption allows a cancelable activity to clean up any work in progress, restore invariants, notify other activities of the cancellation, and then terminate. 

No comments:

Post a Comment