/** * */ package org.oddjob.scheduling; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.apache.log4j.Logger; // We need to augment concurrent Future to ensure // complete cancellation. isDone and isCancelled return true even // if the job is still hogging a thread. class SimpleFuture { private static final Logger logger = Logger.getLogger(SimpleFuture.class); private final RunnableWrapper wrapper; private final Future<?> future; SimpleFuture(RunnableWrapper wrapper, Future<?> future) { this.wrapper = wrapper; this.future = future; } public void cancel() { if (wrapper.isRunning()) { for (int i = 0; i < 10; ++i) { if (!wrapper.interrupt()) { logger.info("Cancelled running [" + wrapper + "]."); break; } logger.info("Cancelling [" + wrapper + "]"); synchronized (this) { try { wait(1000); } catch (InterruptedException e) { logger.warn("Interrupted while cancelling [" + wrapper + "] - It may still be running."); } } } if (wrapper.isRunning()) { logger.warn("Failed to cancel [" + wrapper + "] after ten attempts."); } } else { if (!future.isDone()) { future.cancel(true); logger.info("Cancelled [" + wrapper + "]."); } } } public void waitFor() { try { future.get(); } catch (InterruptedException e) { logger.info("[" + wrapper + "] Wait interrupted."); } catch (CancellationException e) { logger.info("[" + wrapper + "] cancelled."); } catch (ExecutionException e) { logger.error("Execution Exception for [" + wrapper + "].", e); } } }