A thread can be interrupted by another thread using the function interrupt(). Thus, in our earlier example, we can write
p[i].interrupt();
to interrupt thread p[i]. This raises an InterruptedException, which, as we saw, we must catch if the thread is in sleep() or wait().
However, if the thread is actually running when the interrupt arrives, no exception is raised! To identify that an interrupt arrived in such a situation, the thread can check its interrupt status using the function interrupted(), which returns a boolean and clears the interrupt status back to false. Thus, if we want to trap interrupts in p[i].run() both at the sleep(..) and elsewhere, we should rewrite run() as follows:
public void run(){ try{ j = 0; while(!interrupted() && j < 100){ System.out.println("My id is "+id); sleep(1000); // Go to sleep for 1000 ms j++; } catch(InterruptedException e){} } } }
It is also possible to check another thread's interrupt status using isInterrupted(). Thus t.isInterrupted() returns a boolean. However, it does not clear the interrupt flag, unlike interrupted(). Actually, interrupted() is a static function that makes use of isInterrupted() to check the flag of the current thread and then clears its interrupt flag.
Another useful function to spy on the state of another thread is isAlive(). t.isAlive() returns true if the thread t is Runnable or Blocked and false if t is New or Dead. Notice that you cannot use isAlive() to distinguish whether a thread is Runnable or Blocked.
For historical reasons, Java also supports a method stop() to kill another thread and suspend() and resume() to unilaterally suspend and resume a thread (which is not the same as the wait() and notify()/notifyAll() construction). However, these are not supposed to be used because they frequently lead to unpredictable conditions (when a thread dies abruptly) or deadlocks (when suspended threads are not properly resumed).