2008-12-30 11:43:37 -05:00
|
|
|
|
|
|
|
package net.sourceforge.tuned;
|
|
|
|
|
|
|
|
|
2008-12-31 06:54:44 -05:00
|
|
|
import java.util.concurrent.ScheduledFuture;
|
2008-12-30 11:43:37 -05:00
|
|
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
2009-10-15 11:18:57 -04:00
|
|
|
import java.util.concurrent.ThreadFactory;
|
2008-12-30 11:43:37 -05:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2011-12-31 05:45:22 -05:00
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
2008-12-30 11:43:37 -05:00
|
|
|
|
|
|
|
|
|
|
|
public abstract class Timer implements Runnable {
|
|
|
|
|
2009-10-15 11:18:57 -04:00
|
|
|
private final ThreadFactory threadFactory = new DefaultThreadFactory("Timer", Thread.NORM_PRIORITY, true);
|
2008-12-30 11:43:37 -05:00
|
|
|
|
2009-10-15 11:18:57 -04:00
|
|
|
private ScheduledThreadPoolExecutor executor;
|
2008-12-31 06:54:44 -05:00
|
|
|
private ScheduledFuture<?> scheduledFuture;
|
2008-12-30 11:43:37 -05:00
|
|
|
private Thread shutdownHook;
|
|
|
|
|
2011-12-31 05:45:22 -05:00
|
|
|
|
2008-12-30 11:43:37 -05:00
|
|
|
public synchronized void set(long delay, TimeUnit unit, boolean runBeforeShutdown) {
|
2009-10-15 11:18:57 -04:00
|
|
|
// create executor if necessary
|
|
|
|
if (executor == null) {
|
|
|
|
executor = new ScheduledThreadPoolExecutor(1, threadFactory);
|
|
|
|
}
|
2008-12-30 11:43:37 -05:00
|
|
|
|
2009-10-15 11:18:57 -04:00
|
|
|
// cancel existing future task
|
|
|
|
if (scheduledFuture != null) {
|
|
|
|
scheduledFuture.cancel(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
Runnable runnable = this;
|
2008-12-30 11:43:37 -05:00
|
|
|
|
|
|
|
if (runBeforeShutdown) {
|
2011-12-31 05:45:22 -05:00
|
|
|
try {
|
|
|
|
addShutdownHook();
|
|
|
|
} catch (Exception e) {
|
|
|
|
// may fail if running with restricted permissions
|
|
|
|
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getClass().getName() + ": " + e.getMessage());
|
|
|
|
}
|
2008-12-30 11:43:37 -05:00
|
|
|
|
|
|
|
// remove shutdown hook after execution
|
2009-10-15 11:18:57 -04:00
|
|
|
runnable = new Runnable() {
|
2008-12-30 11:43:37 -05:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
Timer.this.run();
|
|
|
|
} finally {
|
2009-10-15 11:18:57 -04:00
|
|
|
cancel();
|
2008-12-30 11:43:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} else {
|
2011-12-31 05:45:22 -05:00
|
|
|
try {
|
|
|
|
// remove existing shutdown hook, if any
|
|
|
|
removeShutdownHook();
|
|
|
|
} catch (Exception e) {
|
|
|
|
// may fail if running with restricted permissions
|
|
|
|
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getClass().getName() + ": " + e.getMessage());
|
|
|
|
}
|
2008-12-30 11:43:37 -05:00
|
|
|
}
|
|
|
|
|
2009-10-15 11:18:57 -04:00
|
|
|
scheduledFuture = executor.schedule(runnable, delay, unit);
|
2008-12-30 11:43:37 -05:00
|
|
|
}
|
|
|
|
|
2011-12-31 05:45:22 -05:00
|
|
|
|
2008-12-30 11:43:37 -05:00
|
|
|
public synchronized void cancel() {
|
|
|
|
removeShutdownHook();
|
2009-10-15 11:18:57 -04:00
|
|
|
|
|
|
|
// stop executor
|
|
|
|
executor.shutdownNow();
|
|
|
|
|
|
|
|
scheduledFuture = null;
|
|
|
|
executor = null;
|
2008-12-30 11:43:37 -05:00
|
|
|
}
|
|
|
|
|
2011-12-31 05:45:22 -05:00
|
|
|
|
2008-12-30 11:43:37 -05:00
|
|
|
private synchronized void addShutdownHook() {
|
|
|
|
if (shutdownHook == null) {
|
|
|
|
shutdownHook = new Thread(this);
|
|
|
|
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-31 05:45:22 -05:00
|
|
|
|
2008-12-30 11:43:37 -05:00
|
|
|
private synchronized void removeShutdownHook() {
|
|
|
|
if (shutdownHook != null) {
|
|
|
|
try {
|
|
|
|
if (shutdownHook != Thread.currentThread()) {
|
|
|
|
// can't remove shutdown hooks anymore, once runtime is shutting down,
|
|
|
|
// so don't remove the shutdown hook, if we are running on the shutdown hook
|
|
|
|
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
shutdownHook = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|