When completing a planned date (in a database), typical scheduling methods (i.e. cron-based or fixed scheduling) are no longer applied. Given the given date, you can accurately schedule the task as follows:
Date now = new Date();
Date next = ... get next date from external source ...
long delay = next.getTime() - now.getTime();
scheduler.schedule(Runnable task, delay, TimeUnit.MILLISECONDS);
It remains to create an effective approach to sending each new task. Below is the TaskDispatcher thread, which schedules each Task based on the following java.util.Date (which you read from the database). No need to check daily; this approach is flexible enough to work with any planning scenario stored in the database.
Follow is a working code illustrating the approach.
; . , TaskDispatcher CountDownLatch.
public class Task implements Runnable {
private final CountDownLatch completion;
public Task(CountDownLatch completion) {
this.completion = completion;
}
@Override
public void run() {
System.out.println("Doing task");
try {
Thread.sleep(60*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
completion.countDown();
}
}
, ScheduledFuture .
public class TaskDispatcher implements Runnable {
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private boolean isInterrupted = false;
@Override
public void run() {
while (!isInterrupted) {
Date now = new Date();
System.out.println("Reading database for next date");
Date next = ... read next data from database ...
long delay = next.getTime() - now.getTime();
System.out.println("Scheduling next task with delay="+delay);
CountDownLatch latch = new CountDownLatch(1);
ScheduledFuture<?> countdown = scheduler.schedule(new Task(latch), delay, TimeUnit.MILLISECONDS);
try {
System.out.println("Blocking until the current job has completed");
latch.await();
} catch (InterruptedException e) {
System.out.println("Thread has been requested to stop");
isInterrupted = true;
}
if (!isInterrupted)
System.out.println("Job has completed normally");
}
scheduler.shutdown();
}
}
TaskDispatcher ( Spring Boot) - , , Spring:
@Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
return new CommandLineRunner() {
public void run(String... args) throws Exception {
executor.execute(new TaskDispatcher());
}
};
}
, .