Timeout Service
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.LinkedList;
/**
* TimeoutService (beta). Here you can register a timeout.
* <p>
* 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();
}
}
}
Related examples in the same category