Network Android

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.LinkedList;
/**
 * TimeoutService (beta). Here you can register a timeout.
 * 


 * Implemented having large scale programs in mind: if you open many concurrent
 * SSH connections that rely on timeouts, then there will be only one timeout
 * thread. Once all timeouts have expired/are cancelled, the thread will (sooner
 * or later) exit. Only after new timeouts arrive a new thread (singleton) will
 * be instantiated.
 * 
 * @author Christian Plattner, plattner@trilead.com
 * @version $Id: TimeoutService.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $
 */
class TimeoutService {
  private static class TimeoutThread extends Thread {
    public void run() {
      synchronized (todolist) {
        while (true) {
          if (todolist.size() == 0) {
            timeoutThread = null;
            return;
          }
          long now = System.currentTimeMillis();
          TimeoutToken tt = (TimeoutToken) todolist.getFirst();
          if (tt.runTime > now) {
            /* Not ready yet, sleep a little bit */
            try {
              todolist.wait(tt.runTime - now);
            } catch (InterruptedException e) {
            }
            /*
             * We cannot simply go on, since it could be that the
             * token was removed (cancelled) or another one has been
             * inserted in the meantime.
             */
            continue;
          }
          todolist.removeFirst();
          try {
            tt.handler.run();
          } catch (Exception e) {
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
//            log.log(20,
  //              "Exeception in Timeout handler:"
    //                + e.getMessage() + "(" + sw.toString()
      //              + ")");
          }
        }
      }
    }
  }
  public static class TimeoutToken implements Comparable {
    private long runTime;
    private Runnable handler;
    private TimeoutToken(long runTime, Runnable handler) {
      this.runTime = runTime;
      this.handler = handler;
    }
    public int compareTo(Object o) {
      TimeoutToken t = (TimeoutToken) o;
      if (runTime > t.runTime)
        return 1;
      if (runTime == t.runTime)
        return 0;
      return -1;
    }
  }
//  private static final Logger log = Logger.getLogger(TimeoutService.class);
  /* The list object is also used for locking purposes */
  private static final LinkedList todolist = new LinkedList();
  private static Thread timeoutThread = null;
  /**
   * It is assumed that the passed handler will not execute for a long time.
   * 
   * @param runTime
   * @param handler
   * @return a TimeoutToken that can be used to cancel the timeout.
   */
  public static final TimeoutToken addTimeoutHandler(long runTime,
      Runnable handler) {
    TimeoutToken token = new TimeoutToken(runTime, handler);
    synchronized (todolist) {
      todolist.add(token);
      Collections.sort(todolist);
      if (timeoutThread != null)
        timeoutThread.interrupt();
      else {
        timeoutThread = new TimeoutThread();
        timeoutThread.setDaemon(true);
        timeoutThread.start();
      }
    }
    return token;
  }
  public static final void cancelTimeoutHandler(TimeoutToken token) {
    synchronized (todolist) {
      todolist.remove(token);
      if (timeoutThread != null)
        timeoutThread.interrupt();
    }
  }
}