| TimeOutController.java |
/*
* $Id: TimeOutController.java,v 1.27 2010/09/29 17:21:48 agoubard Exp $
*
* See the COPYRIGHT file for redistribution and use restrictions.
*/
package org.xins.common;
/**
* Utility class for executing a task with a certain time-out period.
*
* @version $Revision: 1.27 $ $Date: 2010/09/29 17:21:48 $
* @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
*
* @since XINS 1.0.0
*/
public final class TimeOutController {
/**
* Constructs a new <code>TimeOutController</code> object.
*/
private TimeOutController() {
// empty
}
/**
* Runs the specified task with a specific time-out. If the task does
* not finish within the specified time-out period, then the thread
* executing that task is interrupted using the {@link Thread#interrupt()}
* method and a {@link TimeOutException} is thrown.
*
* <p>Note that the specified task could be run either in the current
* thread or in a new thread. In the latter case, no initialization is
* performed. For example, the <em>Nested Diagnostic Context
* identifier</em> (NDC) is not copied from the current thread to the new
* one.
*
* @param task
* the task to run, cannot be <code>null</code>.
*
* @param timeOut
* the timeOut in milliseconds, must be > 0.
*
* @throws IllegalArgumentException
* if <code>task == null || timeOut <= 0</code>.
*
* @throws IllegalThreadStateException
* if the specified task is a {@link Thread} that is already started.
*
* @throws SecurityException
* if the thread did not finish within the total time-out period, but
* the interruption of the thread was disallowed (see
* {@link Thread#interrupt()}); consequently, the thread may still be
* running.
*
* @throws TimeOutException
* if the thread did not finish within the total time-out period and was
* interrupted.
*/
public static void execute(Runnable task, int timeOut)
throws IllegalArgumentException,
IllegalThreadStateException,
SecurityException,
TimeOutException {
// Check preconditions
MandatoryArgumentChecker.check("task", task);
if (timeOut <= 0) {
throw new IllegalArgumentException("timeOut (" + timeOut + ") <= 0");
}
// We need a Thread instance. If the argument is already a Thread
// instance, then use it, otherwise construct a new Thread instance.
Thread thread;
if (task instanceof Thread) {
thread = (Thread) task;
} else {
// XXX: To improve performance and manageability, we could use a
// thread pool like the one that is available in J2SE 5.0.
thread = new Thread(task);
}
// Start the thread. This may throw an IllegalThreadStateException.
thread.start();
// Wait for the thread to finish, within limits
try {
thread.join(timeOut);
} catch (InterruptedException exception) {
Utils.logIgnoredException(exception);
}
// If the thread is still running at this point, it should stop
if (thread.isAlive()) {
// Interrupt the thread. This may throw a SecurityException
thread.interrupt();
throw new TimeOutException();
}
}
}