1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
package compbio.stat.servlet.util;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* A facility for threads to schedule recurring tasks for future
* execution in a background thread.
* <p>
* This class is thread-safe: multiple threads can share a single
* <code>Scheduler</code> object without the need for external synchronization.
* <p>
* Implementation note: internally <code>Scheduler</code> uses a
* <code>java.util.Timer</code> to schedule tasks.
*/
public class Scheduler {
class SchedulerTimerTask extends TimerTask {
private SchedulerTask schedulerTask;
private ScheduleIterator iterator;
public SchedulerTimerTask(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
this.schedulerTask = schedulerTask;
this.iterator = iterator;
}
public void run() {
schedulerTask.run();
reschedule(schedulerTask, iterator);
}
}
private final Timer timer = new Timer();
public Scheduler() {
}
/**
* Terminates this <code>Scheduler</code>, discarding any currently scheduled tasks.
* Does not interfere with a currently executing task (if it exists). Once a scheduler
* has been terminated, its execution thread terminates gracefully, and no more tasks
* may be scheduled on it.
* <p>
* Note that calling this method from within the run method of a scheduler task that was
* invoked by this scheduler absolutely guarantees that the ongoing task execution is the
* last task execution that will ever be performed by this scheduler.
* <p>
* This method may be called repeatedly; the second and subsequent calls have no effect.
*/
public void cancel() {
timer.cancel();
}
/**
* Schedules the specified task for execution according to the specified schedule. If times
* specified by the <code>ScheduleIterator</code> are in the past they are scheduled for
* immediate execution.
* <p>
*
* @param schedulerTask task to be scheduled
* @param iterator iterator that describes the schedule
* @throws IllegalStateException if task was already scheduled or cancelled, scheduler was
* cancelled, or scheduler thread terminated.
*/
public void schedule(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
Date time = iterator.next();
if (time == null) {
schedulerTask.cancel();
} else {
synchronized (schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.VIRGIN) {
throw new IllegalStateException("Task already scheduled " +
"or cancelled");
}
schedulerTask.state = SchedulerTask.SCHEDULED;
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}
private void reschedule(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
Date time = iterator.next();
if (time == null) {
schedulerTask.cancel();
} else {
synchronized (schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.CANCELLED) {
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}
}
}
|