/* * Created on May 5, 2004 */ package cyrille.thread; import org.apache.commons.lang.IllegalClassException; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author <a href="mailto:cleclerc@pobox.com">Cyrille Le Clerc </a> */ public class TimedRunnableSubOptimal implements Runnable, Comparable { private final static Log log = LogFactory.getLog(TimedRunnableSubOptimal.class); private long m_millis; private Runnable m_runnable; private long m_startTime; private boolean m_timedOut; /** * */ public TimedRunnableSubOptimal(Runnable runnable, long millis) { super(); this.m_runnable = runnable; this.m_millis = millis; } /** * @return Returns the timedOut. */ public boolean isTimedOut() { return this.m_timedOut; } /** * @see java.lang.Runnable#run() */ public void run() { this.m_startTime = System.currentTimeMillis(); boolean traceEnabled = log.isTraceEnabled(); if (traceEnabled) { log.trace("> run " + this.toString()); } Thread executionThread = new Thread(this.m_runnable, Thread.currentThread().getName() + "-execution"); executionThread.start(); try { executionThread.join(this.m_millis); } catch (InterruptedException e) { log.error("Interruption in " + this.toString(), e); } finally { if (executionThread.isAlive()) { this.m_timedOut = true; stopThreadSilently(executionThread); } else { this.m_timedOut = false; } } if (traceEnabled) { log.trace("< run "); } } private void stopThreadSilently(Thread thread) { boolean traceEnabled = log.isTraceEnabled(); if (traceEnabled) { log.trace("> stopThreadSilently[thread=" + thread + "]"); } // cleanup the new thread using an appropriate means // eg. stop(), interrupt() or whatever log.trace("Interrupt thread "); thread.interrupt(); try { thread.join(500); } catch (InterruptedException e) { log.error(e.getMessage(), e); } finally { if (thread.isAlive()) { log.trace("Destroy thread "); thread.destroy(); } } } /** * @see java.lang.Object#toString() */ @Override public String toString() { return new ToStringBuilder(this).append("startTime", this.m_startTime).append("millis", this.m_millis).append("runnable", this.m_runnable) .toString(); } /** * <p> * Compares the underlying <code>TimedRunnable#m_runnable<code> with :<br> * - if the other object is a <code>TimedRunnable</code>, the other <code>TimedRunnable#m_runnable<code> * - otherwise with the other object * </p> * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(Object o) { if (!(this.m_runnable instanceof Comparable)) { throw new IllegalClassException(Comparable.class, this.m_runnable.getClass()); } Comparable comparable = (Comparable) this.m_runnable; Comparable otherComparable; if (o instanceof TimedRunnableSubOptimal) { TimedRunnableSubOptimal otherTimedRunnable = (TimedRunnableSubOptimal) o; if (!(otherTimedRunnable.m_runnable instanceof Comparable)) { throw new IllegalClassException(Comparable.class, otherTimedRunnable.m_runnable.getClass()); } otherComparable = (Comparable) otherTimedRunnable.m_runnable; } else if (!(o instanceof Comparable)) { throw new IllegalClassException(Comparable.class, o.getClass()); } else { otherComparable = (Comparable) o; } return comparable.compareTo(otherComparable); } }