gpt4 book ai didi

spring - 使用 ThreadPoolTask​​Executor 在特定日期调用方法

转载 作者:行者123 更新时间:2023-12-02 11:34:08 25 4
gpt4 key购买 nike

我有一个方法,我希望使用 Spring 运行一次,并且它需要在给定的 java.util.Date (或 LocalDateTime)上运行。我计划将该方法应执行的所有日期保留到数据源。它应该异步运行。

一种方法是每天检查数据库中的日期,如果日期已过但尚未执行,则执行该方法。有更好的办法吗?

我知道Spring提供了一个ThreadPoolTask​​Scheduler和一个ThreadPoolTask​​Executor。我正在从 TaskScheduler 界面查看 ScheduledFuture 计划(Runnable task, Date startTime) 。我是否需要创建一个 Runnable Spring 托管 bean 来调用我的方法?或者是否有更简单的注释可以做到这一点?一个例子确实会有帮助。

( Looked here too. )

最佳答案

通过将计划日期外部化(到数据库),典型的计划实践(即基于 cron 的计划或固定计划)不再适用。给定目标日期,您可以准确地安排任务,如下所示:

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);

剩下的就是创建一种高效方法来分派(dispatch)每个新任务。下面有一个 TaskDispatcher 线程,它根据下一个 java.util.Date(您从数据库读取)来调度每个任务。无需每天检查;这种方法足够灵活,可以适用于数据库中存储的任何调度场景。

接下来是说明该方法的工作代码。

使用的示例任务;在这种情况下,只是休眠固定的时间。当任务完成时,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());
}
};
}

请告诉我此方法是否适合您的用例。

关于spring - 使用 ThreadPoolTask​​Executor 在特定日期调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44035991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com