001: /*
002: * $Id: TimeOutController.java,v 1.25 2007/03/16 09:54:58 agoubard Exp $
003: *
004: * Copyright 2003-2007 Orange Nederland Breedband B.V.
005: * See the COPYRIGHT file for redistribution and use restrictions.
006: */
007: package org.xins.common;
008:
009: /**
010: * Utility class for executing a task with a certain time-out period.
011: *
012: * @version $Revision: 1.25 $ $Date: 2007/03/16 09:54:58 $
013: * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
014: *
015: * @since XINS 1.0.0
016: */
017: public final class TimeOutController {
018:
019: /**
020: * Constructs a new <code>TimeOutController</code> object.
021: */
022: private TimeOutController() {
023: // empty
024: }
025:
026: /**
027: * Runs the specified task with a specific time-out. If the task does
028: * not finish within the specified time-out period, then the thread
029: * executing that task is interrupted using the {@link Thread#interrupt()}
030: * method and a {@link TimeOutException} is thrown.
031: *
032: * <p>Note that the specified task could be run either in the current
033: * thread or in a new thread. In the latter case, no initialization is
034: * performed. For example, the <em>Nested Diagnostic Context
035: * identifier</em> (NDC) is not copied from the current thread to the new
036: * one.
037: *
038: * @param task
039: * the task to run, cannot be <code>null</code>.
040: *
041: * @param timeOut
042: * the timeOut in milliseconds, must be > 0.
043: *
044: * @throws IllegalArgumentException
045: * if <code>task == null || timeOut <= 0</code>.
046: *
047: * @throws IllegalThreadStateException
048: * if the specified task is a {@link Thread} that is already started.
049: *
050: * @throws SecurityException
051: * if the thread did not finish within the total time-out period, but
052: * the interruption of the thread was disallowed (see
053: * {@link Thread#interrupt()}); consequently, the thread may still be
054: * running.
055: *
056: * @throws TimeOutException
057: * if the thread did not finish within the total time-out period and was
058: * interrupted.
059: */
060: public static void execute(Runnable task, int timeOut)
061: throws IllegalArgumentException,
062: IllegalThreadStateException, SecurityException,
063: TimeOutException {
064:
065: // Check preconditions
066: MandatoryArgumentChecker.check("task", task);
067: if (timeOut <= 0) {
068: throw new IllegalArgumentException("timeOut (" + timeOut
069: + ") <= 0");
070: }
071:
072: // We need a Thread instance. If the argument is already a Thread
073: // instance, then use it, otherwise construct a new Thread instance.
074: Thread thread;
075: if (task instanceof Thread) {
076: thread = (Thread) task;
077: } else {
078: // XXX: To improve performance and manageability, we could use a
079: // thread pool like the one that is available in J2SE 5.0.
080: thread = new Thread(task);
081: }
082:
083: // Start the thread. This may throw an IllegalThreadStateException.
084: thread.start();
085:
086: // Wait for the thread to finish, within limits
087: try {
088: thread.join(timeOut);
089: } catch (InterruptedException exception) {
090: Utils.logIgnoredException(exception);
091: }
092:
093: // If the thread is still running at this point, it should stop
094: if (thread.isAlive()) {
095:
096: // Interrupt the thread. This may throw a SecurityException
097: thread.interrupt();
098:
099: throw new TimeOutException();
100: }
101: }
102: }
|