gpt4 book ai didi

java - 如何使用 ScheduledExecutorService 每天在特定时间运行特定任务?

转载 作者:行者123 更新时间:2023-12-01 23:54:25 26 4
gpt4 key购买 nike

我尝试每天早上 5 点运行某项任务。因此,我决定使用 ScheduledExecutorService 来实现此目的,但到目前为止我已经看到了一些示例,这些示例展示了如何每隔几分钟运行一次任务。

而且我找不到任何示例来说明如何每天在早上的特定时间(上午 5 点)运行任务,并考虑夏令时的事实 -

下面是我的代码,每 15 分钟运行一次 -

public class ScheduledTaskExample {
private final ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);

public void startScheduleTask() {
/**
* not using the taskHandle returned here, but it can be used to cancel
* the task, or check if it's done (for recurring tasks, that's not
* going to be very useful)
*/
final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(
new Runnable() {
public void run() {
try {
getDataFromDatabase();
}catch(Exception ex) {
ex.printStackTrace(); //or loggger would be better
}
}
}, 0, 15, TimeUnit.MINUTES);
}

private void getDataFromDatabase() {
System.out.println("getting data...");
}

public static void main(String[] args) {
ScheduledTaskExample ste = new ScheduledTaskExample();
ste.startScheduleTask();
}
}

有没有什么办法,我可以使用 ScheduledExecutorService 安排任务在每天早上 5 点运行,同时考虑到夏令时的事实?

还有 TimerTask 更适合这个还是 ScheduledExecutorService

最佳答案

与当前的 java SE 8 版本一样,它具有出色的日期时间 API 和 java.time这种计算可以更容易地完成,而不是使用 java.util.Calendarjava.util.Date .

现在作为根据您的用例安排任务的示例:

ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
ZonedDateTime nextRun = now.withHour(5).withMinute(0).withSecond(0);
if(now.compareTo(nextRun) > 0)
nextRun = nextRun.plusDays(1);

Duration duration = Duration.between(now, nextRun);
long initialDelay = duration.getSeconds();

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(new MyRunnableTask(),
initialDelay,
TimeUnit.DAYS.toSeconds(1),
TimeUnit.SECONDS);

initialDelay计算要求调度程序延迟 TimeUnit.SECONDS 中的执行。对于此用例,单位毫秒及以下的时差问题似乎可以忽略不计。但您仍然可以使用duration.toMillis()TimeUnit.MILLISECONDS用于以毫秒为单位处理调度计算。

And also TimerTask is better for this or ScheduledExecutorService?

否: ScheduledExecutorService看起来比TimerTask更好。 StackOverflow has already an answer for you .

来自@PaddyD,

You still have the issue whereby you need to restart this twice a yearif you want it to run at the right local time. scheduleAtFixedRatewon't cut it unless you are happy with the same UTC time all year.

因为这是真的,而且 @PaddyD 已经给出了解决方法(+1),我提供了一个使用 Java8 日期时间 API 的工作示例 ScheduledExecutorServiceUsing daemon thread is dangerous

class MyTaskExecutor
{
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
MyTask myTask;
volatile boolean isStopIssued;

public MyTaskExecutor(MyTask myTask$)
{
myTask = myTask$;

}

public void startExecutionAt(int targetHour, int targetMin, int targetSec)
{
Runnable taskWrapper = new Runnable(){

@Override
public void run()
{
myTask.execute();
startExecutionAt(targetHour, targetMin, targetSec);
}

};
long delay = computeNextDelay(targetHour, targetMin, targetSec);
executorService.schedule(taskWrapper, delay, TimeUnit.SECONDS);
}

private long computeNextDelay(int targetHour, int targetMin, int targetSec)
{
LocalDateTime localNow = LocalDateTime.now();
ZoneId currentZone = ZoneId.systemDefault();
ZonedDateTime zonedNow = ZonedDateTime.of(localNow, currentZone);
ZonedDateTime zonedNextTarget = zonedNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec);
if(zonedNow.compareTo(zonedNextTarget) > 0)
zonedNextTarget = zonedNextTarget.plusDays(1);

Duration duration = Duration.between(zonedNow, zonedNextTarget);
return duration.getSeconds();
}

public void stop()
{
executorService.shutdown();
try {
executorService.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException ex) {
Logger.getLogger(MyTaskExecutor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

注意:

  • MyTask是一个具有函数 execute 的接口(interface).
  • parking 时ScheduledExecutorService ,始终使用awaitTermination调用shutdown后关于它:您的任务总是有可能被卡住/死锁,并且用户将永远等待。

我之前用日历给出的例子只是我提到的一个想法,我避免了精确时间计算和夏令时问题。根据@PaddyD的提示更新了解决方案

关于java - 如何使用 ScheduledExecutorService 每天在特定时间运行特定任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58209919/

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