Calling a method on specific dates using ThreadPoolTaskExecutor

I have a method that I want to run once using Spring, and it should run on this java.util.Date(or LocalDateTimeas an alternative). I plan to keep all the dates that the method must complete for the data source. It must run asynchronously.

One way is to check the database every day for a date and execute the method if the date has passed and has not been completed. Is there a better way?

I know what Spring offers ThreadPoolTaskSchedulerand ThreadPoolTaskExecutor. I look ScheduledFuture schedule(Runnable task, Date startTime)from the interface TaskScheduler. Do I need to create a RunnableSpring managed bean just to call my method? Or is there a simpler annotation that will do this? An example will really help.

( Looked here too. )

+4
source share
2 answers

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);  // Simulate the job taking 60 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        completion.countDown();     // Signal that the job is complete
    }

}

, 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 ...

            //Date next = new Date();   // Used as test
            //next.setTime(now.getTime()+10*1000); // Used as test

            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(); // Or use another one of your liking
}

@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
    return new CommandLineRunner() {
        public void run(String... args) throws Exception {
            executor.execute(new TaskDispatcher());
        }
    };
}

, .

+2

@Scheduled. , .

@Scheduled(cron="*/5 * * * * MON-FRI")
public void scheduledDateWork() {
    Date date = new Date(); //or use DAO call to look up date in database

    executeLogic(date);
}

Cron :

"0 0 * * * *" = the top of every hour of every day.
"*/10 * * * * *" = every ten seconds.
"0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day.
"0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.
"0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays
"0 0 0 25 12 ?" = every Christmas Day at midnight
0

Source: https://habr.com/ru/post/1677401/


All Articles