Watchdog timers can be used in many programming contexts, not just low-level hardware systems. For example, a thread responsible for downloading a file might hang for reasons beyond the control of the programmer if there is a problem with the network library. One wants one's program to recover with grace and reliability, so one uses a watchdog thread. What follows is an example of a watchdog thread implemented in Java. In normal use one would use and anonymous inner subclass of Watchdog, overriding killed() to perform some cleanup should the watched thread be killed.

Note also that this implementation avoids part of the "multiple clients" problem described by hobyrne below; multiple threads sharing a watchdog can each set a different index in the boolean semaphore. Should any thread fail to set its part of the semaphore, the watchdog will be tripped. It is the responsibility of the programmer to kill the individual "extra" threads as necessary by overriding killed(). Still, it is probably better to have one Watchdog per thread.



/** This class implements a 'watchdog' thread: one which oversees the operation
 * of another thread.  A <code>boolean[]</code> is used as a semaphore between the
 * watchdog thread and the watched thread. Before a specified interval has
 * elapsed, the watched thread indicates through the semaphore that it is
 * functioning correctly.  That is, each element of the boolean array must
 * be set to <tt>true</tt> in turn within <tt>sleep</tt> milliseconds.
 * Otherwise, the watchdog will terminate the watched thread.  Elements of the 
 * semaphore are automatically cleared by the watchdog after they are read,
 * and the watchdog returns to the first element of the semaphore after
 * the last element is checked.
 * <p>
 * The watchdog automatically terminates if the watched thread stops 
 * (i.e. <tt>isAlive()</tt> returns <tt>false</tt>) and is a daemon
 * thread so that it will not prevent the VM from exiting.
 *
 * @author Pyrogenic
 */
public class Watchdog extends Thread {

    Thread watched;
    int sleep;
    boolean[] semaphore;
    int length;

    boolean ok;
    boolean run = true;

    public Watchdog(final Thread watched, 
                    final int sleep, 
                    final boolean[] semaphore) {
	this(null, watched, sleep, semaphore);
    }

    public Watchdog(final ThreadGroup threadGroup, 
                    final Thread watched, 
                    final int sleep,
                    final boolean[] semaphore) {
	super(threadGroup, "Watching " + watched);
	this.watched = watched;
	this.sleep = sleep;
	this.semaphore = semaphore;
	length = semaphore.length;
	setDaemon(true);
    }

    public void run() {
        while (run && watched.isAlive()) {
            ok = true;
            for (int i = 0; i < length; i++) {
                if (!semaphore[i]) {
                    try {
                        sleep(sleep);
                    } catch (InterruptedException e) {
                    }
                }
                if (!run) {
                    ok = true;
                    break;
                }
                ok = semaphore[i] && ok;
                semaphore[i] = false;
            }
            if (!ok) {
                trigger();
            }
        }
    }

    /** invoke this method to trigger the watchdog regardless of the state of the semaphore.
     * Note that the <CODE>@warn()</CODE> method is invoked before the
     * watched thread is killed, and the result is still heeded.
     * @see #warn
     */
    public void trigger() {
        if (warn()) {
            watched.stop();
            killed();
        }
    }

    /** invoked before the watchdog terminates the thread it is watching.
     * The default implementation returns <CODE>true</CODE>.  Override this
     * method if you might want to cancel the shutdown of the watched thread.
     * <P>
     * In the event that a shutdown is cancelled, the watchdog will go back
     * to sleep, then check the semaphores again after the sleep time.
     *
     * @return  whether to continue shutting down the watched thread.  Return
     *        <CODE>true</CODE> to continue the shutdown.  Return
     *        <CODE>false</CODE> to cancel the shutdown.
     */
    protected boolean warn() {
        return true;
    }

    /** invoked after the watched thread has been killed.  The default
     * implementation does nothing. Subclasses can use this as an
     * opportunity to clean up after the killed thread by closing streams,
     * removing temporary files, etc.
     */
    protected void killed() {
        /* does nothing */
    }

    /** invoke this method to stop the watchdog in a clean manner.  The
     * watched thread will be left alone, and the watchdog will exit.
     */
    public void cease() {
        run = false;
        interrupt();
    }

}