Added more to readme and javadoc.
This commit is contained in:
parent
967dcfffe3
commit
f2b2b8667c
24
README.md
24
README.md
|
@ -1,2 +1,22 @@
|
||||||
# SimplyScheduled
|
# Simply Scheduled
|
||||||
Lightweight Cron-Like Scheduling Library for Java
|
|
||||||
|
This is a very simple cron-like mechanism for scheduling tasks to execute at scheduled points in time. Here's an example:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Runnable job = () -> System.out.println("Doing some work...");
|
||||||
|
Schedule schedule = new RepeatingSchedule(ChronoUnit.SECONDS, 5);
|
||||||
|
Scheduler scheduler = new BasicScheduler();
|
||||||
|
scheduler.add(new Task(job, schedule));
|
||||||
|
scheduler.start();
|
||||||
|
```
|
||||||
|
> In the above example, we create a new job that simply prints a string to standard output. We create a schedule that repeats the task every 5 seconds. Finally, we add the job and schedule together as a Task, add that task to a scheduler, and start the scheduler.
|
||||||
|
|
||||||
|
Besides the `RepeatingSchedule`, this module also includes the following pre-made schedule implementations:
|
||||||
|
|
||||||
|
* `DailySchedule` - Executes a task once per day, at a specified time.
|
||||||
|
* `HourlySchedule` - Executes a task once per hour, at a specified minute of the hour.
|
||||||
|
* `MinutelySchedule` - Executes a task once per minute, at a specified second.
|
||||||
|
|
||||||
|
## Extensibility
|
||||||
|
|
||||||
|
It is very simple to provide your own custom Schedule implementation if you want a more specific, fine-tuned schedule than what is provided here. Furthermore, you can also provide your own Scheduler implementation, if you prefer to use a different mechanism than the default dynamic thread pool executor service.
|
||||||
|
|
|
@ -40,11 +40,12 @@ public class BasicScheduler extends Thread implements Scheduler {
|
||||||
try {
|
try {
|
||||||
Task nextTask = this.tasks.take();
|
Task nextTask = this.tasks.take();
|
||||||
Instant now = this.clock.instant();
|
Instant now = this.clock.instant();
|
||||||
long waitTime = nextTask.getSchedule().computeNextExecutionTime(now).toEpochMilli() - now.toEpochMilli();
|
long waitTime = nextTask.getSchedule().getNextExecutionTime(now).toEpochMilli() - now.toEpochMilli();
|
||||||
if (waitTime > 0) {
|
if (waitTime > 0) {
|
||||||
Thread.sleep(waitTime);
|
Thread.sleep(waitTime);
|
||||||
}
|
}
|
||||||
this.executorService.execute(nextTask.getRunnable());
|
this.executorService.execute(nextTask.getRunnable());
|
||||||
|
nextTask.getSchedule().markExecuted(this.clock.instant());
|
||||||
this.tasks.put(nextTask); // Put the task back in the queue.
|
this.tasks.put(nextTask); // Put the task back in the queue.
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
this.setRunning(false);
|
this.setRunning(false);
|
||||||
|
|
|
@ -2,6 +2,10 @@ package nl.andrewlalis.simply_scheduled.schedule;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A daily schedule plans for the execution of a task once per day, at a
|
||||||
|
* specified local time.
|
||||||
|
*/
|
||||||
public class DailySchedule implements Schedule {
|
public class DailySchedule implements Schedule {
|
||||||
private final ZoneId zoneId;
|
private final ZoneId zoneId;
|
||||||
private final LocalTime time;
|
private final LocalTime time;
|
||||||
|
@ -16,7 +20,7 @@ public class DailySchedule implements Schedule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instant computeNextExecutionTime(Instant referenceInstant) {
|
public Instant getNextExecutionTime(Instant referenceInstant) {
|
||||||
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
||||||
LocalDate currentDay = LocalDate.from(referenceInstant);
|
LocalDate currentDay = LocalDate.from(referenceInstant);
|
||||||
ZonedDateTime sameDayExecution = currentDay.atTime(this.time).atZone(this.zoneId);
|
ZonedDateTime sameDayExecution = currentDay.atTime(this.time).atZone(this.zoneId);
|
||||||
|
|
|
@ -5,6 +5,10 @@ import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An hourly schedule is used to execute a task once per hour, at a specific
|
||||||
|
* minute of the hour.
|
||||||
|
*/
|
||||||
public class HourlySchedule implements Schedule {
|
public class HourlySchedule implements Schedule {
|
||||||
private final ZoneId zoneId;
|
private final ZoneId zoneId;
|
||||||
private final int minute;
|
private final int minute;
|
||||||
|
@ -22,7 +26,7 @@ public class HourlySchedule implements Schedule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instant computeNextExecutionTime(Instant referenceInstant) {
|
public Instant getNextExecutionTime(Instant referenceInstant) {
|
||||||
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
||||||
int currentMinute = currentTime.getMinute();
|
int currentMinute = currentTime.getMinute();
|
||||||
if (currentMinute < this.minute) {
|
if (currentMinute < this.minute) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class MinutelySchedule implements Schedule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instant computeNextExecutionTime(Instant referenceInstant) {
|
public Instant getNextExecutionTime(Instant referenceInstant) {
|
||||||
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
||||||
int currentSecond = currentTime.getSecond();
|
int currentSecond = currentTime.getSecond();
|
||||||
if (currentSecond >= this.second) {
|
if (currentSecond >= this.second) {
|
||||||
|
|
|
@ -30,12 +30,15 @@ public class RepeatingSchedule implements Schedule {
|
||||||
* @return The next instant to execute the task at.
|
* @return The next instant to execute the task at.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Instant computeNextExecutionTime(Instant referenceInstant) {
|
public Instant getNextExecutionTime(Instant referenceInstant) {
|
||||||
if (this.lastExecution == null) {
|
if (this.lastExecution == null) {
|
||||||
this.lastExecution = referenceInstant;
|
this.lastExecution = referenceInstant;
|
||||||
}
|
}
|
||||||
Instant nextExecution = this.lastExecution.plus(multiple, unit);
|
return this.lastExecution.plus(multiple, unit);
|
||||||
this.lastExecution = nextExecution;
|
}
|
||||||
return nextExecution;
|
|
||||||
|
@Override
|
||||||
|
public void markExecuted(Instant instant) {
|
||||||
|
this.lastExecution = instant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,18 @@ public interface Schedule {
|
||||||
* produce an instant sometime in the future at which the next execution of
|
* produce an instant sometime in the future at which the next execution of
|
||||||
* a task should happen.
|
* a task should happen.
|
||||||
*
|
*
|
||||||
* <p>
|
|
||||||
* <strong>Note that certain implementations may introduce side-effects
|
|
||||||
* when this method is called more than once.</strong>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param referenceInstant The instant representing the current time.
|
* @param referenceInstant The instant representing the current time.
|
||||||
* @return An instant in the future indicating the next time at which a task
|
* @return An instant in the future indicating the next time at which a task
|
||||||
* using this schedule should be executed.
|
* using this schedule should be executed.
|
||||||
*/
|
*/
|
||||||
Instant computeNextExecutionTime(Instant referenceInstant);
|
Instant getNextExecutionTime(Instant referenceInstant);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called on the schedule as an indication that the scheduler
|
||||||
|
* should move on to planning the next execution time.
|
||||||
|
* @param instant The instant at which the schedule's task(s) were executed.
|
||||||
|
*/
|
||||||
|
default void markExecuted(Instant instant) {
|
||||||
|
// Default no-op.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,6 @@ public class Task implements Comparable<Task>{
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Task o) {
|
public int compareTo(Task o) {
|
||||||
Instant now = clock.instant();
|
Instant now = clock.instant();
|
||||||
return this.schedule.computeNextExecutionTime(now).compareTo(o.getSchedule().computeNextExecutionTime(now));
|
return this.schedule.getNextExecutionTime(now).compareTo(o.getSchedule().getNextExecutionTime(now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class SchedulerTest {
|
||||||
scheduler.addTask(task);
|
scheduler.addTask(task);
|
||||||
scheduler.start();
|
scheduler.start();
|
||||||
System.out.println("Now: " + clock.instant().toString());
|
System.out.println("Now: " + clock.instant().toString());
|
||||||
System.out.println("Next task execution: " + task.getSchedule().computeNextExecutionTime(clock.instant()));
|
System.out.println("Next task execution: " + task.getSchedule().getNextExecutionTime(clock.instant()));
|
||||||
System.out.printf("Waiting %d seconds for task to run...", secondsLeft);
|
System.out.printf("Waiting %d seconds for task to run...", secondsLeft);
|
||||||
assertFalse(flag.get());
|
assertFalse(flag.get());
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue