Skip to content

Instantly share code, notes, and snippets.

@aleung
Created May 27, 2013 10:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aleung/5656449 to your computer and use it in GitHub Desktop.
Save aleung/5656449 to your computer and use it in GitHub Desktop.
A simple Java scheduler, which execute scheduled tasks in current thread.
package leoliang.common;
import com.google.common.base.Preconditions;
/**
* Usage example: Run 15 times in every 250ms, begins at 5 seconds later.
*
* <pre>
Scheduler.every(250, Scheduler.TimeUnit.MILLISECOND)
.beginsAt(System.currentTimeMillis() + 5000)
.times(15)
.execute(new Runnable() {
public void run() {
// do something
}
});
* </pre>
*/
public class Scheduler {
public enum TimeUnit {
MILLISECOND(1), SECOND(1000), MINUTE(1000 * 60);
public final long milliseconds;
private TimeUnit(long milliseconds) {
this.milliseconds = milliseconds;
}
}
private long firstExecutionMillisecond;
private long intervalMillisecond;
private long stopsBeforeMillisecond = Long.MAX_VALUE;
private int executionTimes = Integer.MAX_VALUE;
protected Scheduler() {
// nothing to do
}
public static Scheduler every(long interval, TimeUnit unit) {
Scheduler scheduler = new Scheduler();
scheduler.intervalMillisecond = interval * unit.milliseconds;
return scheduler;
}
public static long millisecondOnNextSecond() {
long current = System.currentTimeMillis();
return (current / 1000) * 1000;
}
/**
* Set the first execution time. If not set, first execution will be at the time that {@link #execute(Runnable)} is
* called.
*
* @param millisecond
* @return
*/
public Scheduler beginsAt(long millisecond) {
firstExecutionMillisecond = millisecond;
return this;
}
/**
* Limit that last execution should before a specific moment.
*
* @param executionTimes
* @return
*/
public Scheduler stopsBefore(long millisecond) {
stopsBeforeMillisecond = millisecond;
return this;
}
/**
* Set the total times of execution.
*
* @param executionTimes
* @return
*/
public Scheduler times(int executionTimes) {
this.executionTimes = executionTimes;
return this;
}
/**
* Execute the task as schedule. The execution is in current thread. Missing schedule will be skipped.
*
* @param scheduleTask
*/
public void execute(Runnable task) {
Preconditions.checkArgument(intervalMillisecond > 0, "Interval is not set.");
try {
long nextFireMillisecond;
if (firstExecutionMillisecond > 0) {
fireAt(firstExecutionMillisecond, task);
nextFireMillisecond = firstExecutionMillisecond + intervalMillisecond;
} else {
nextFireMillisecond = System.currentTimeMillis() + intervalMillisecond;
task.run();
}
int executedTimes = 1;
while ((executedTimes < executionTimes) && (nextFireMillisecond < stopsBeforeMillisecond)) {
fireAt(nextFireMillisecond, task);
executedTimes++;
nextFireMillisecond += intervalMillisecond;
}
} catch (InterruptedException e) {
return;
}
}
private void fireAt(long millisecond, Runnable task) throws InterruptedException {
long sleepMillis = millisecond - System.currentTimeMillis();
if (sleepMillis < 0) {
return; // schedule missed, skip
}
if (sleepMillis > 0) {
Thread.sleep(sleepMillis);
}
task.run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment