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

编程入门 行业动态 更新时间:2024-10-09 03:28:28
本文介绍了如何使用ScheduledExecutorService在特定时间每天运行某些任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我每天凌晨5点都在尝试完成某项任务。所以我决定使用 ScheduledExecutorService ,但到目前为止,我已经看到了示例,显示了如何每隔几分钟运行一次任务。

I am trying to run a certain task everyday at 5 AM in the morning. So I decided to use ScheduledExecutorService for this but so far I have seen examples which shows how to run task every few minutes.

我无法找到任何示例,说明如何在早上的特定时间(早上5点)每天运行一项任务,同时考虑到夏令时也是 -

And I am not able to find any example which shows how to run a task every day at a particular time (5 AM) in the morning and also considering the fact of daylight saving time as well -

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

Below is my code which will run every 15 minutes -

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

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

Is there any way, I can schedule a task to run every day 5 AM in the morning using ScheduledExecutorService considering the fact of daylight saving time as well?

还有 TimerTask 更适合这个或 ScheduledExecutorService ?

推荐答案

与目前的Java SE 8版本一样,它的优秀日期时间API与 java.time 相比,这些计算可以更容易地完成使用 java.util.Calendar 和 java.util.Date 。

As with the present java SE 8 release with it's excellent date time API with java.time these kind of calculation can be done more easily instead of using java.util.Calendar and java.util.Date.

  • 使用此新API的日期时间类即LocalDateTime
  • 使用 ZonedDateTime 类,用于处理特定于时区的计算,包括夏令时问题。您可以在此处找到教程和示例。
  • Use date time class's i.e. LocalDateTime of this new API
  • Use ZonedDateTime class to handle Time Zone specific calculation including Daylight Saving issues. You will find tutorial and example here.

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

Now as a sample example for scheduling a task with your use case:

LocalDateTime localNow = LocalDateTime.now(); ZoneId currentZone = ZoneId.of("America/Los_Angeles"); ZonedDateTime zonedNow = ZonedDateTime.of(localNow, currentZone); ZonedDateTime zonedNext5 ; zonedNext5 = zonedNow.withHour(5).withMinute(0).withSecond(0); if(zonedNowpareTo(zonedNext5) > 0) zonedNext5 = zonedNext5.plusDays(1); Duration duration = Duration.between(zonedNow, zonedNext5); long initalDelay = duration.getSeconds(); ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(new MyRunnableTask(), initalDelay, 24*60*60, TimeUnit.SECONDS);

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

The initalDelay is computed to ask the scheduler to delay the execution in TimeUnit.SECONDS. Time difference issues with unit milliseconds and below seems to be negligible for this use case. But you can still make use of duration.toMillis() and TimeUnit.MILLISECONDS for handling the scheduling computaions in milliseconds.

而且TimerTask对于这个或者ScheduledExecutorService更好吗?

And also TimerTask is better for this or ScheduledExecutorService?

NO: ScheduledExecutorService 似乎比 TimerTask 更好。 StackOverflow已经为您提供了答案。

NO: ScheduledExecutorService seemingly better than TimerTask. StackOverflow has already an answer for you.

来自@PaddyD,

您仍然遇到需要的问题如果您希望它在当地时间运行,则每年重启两次。 scheduleAtFixedRate 不会削减它,除非你对全年相同的UTC时间感到满意。

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

因为它是真的, @PaddyD已经给出了一个解决方法(给他+1),我提供了一个带有 ScheduledExecutorService 的Java8日期时间API的工作示例。 使用守护程序线程是危险的

As it is true and @PaddyD already has given a workaround(+1 to him), I am providing a working example with Java8 date time API with ScheduledExecutorService. Using 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(zonedNowpareTo(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 是一个功能的界面执行。
  • 在停止 ScheduledExecutorService 时,在调用<$ c $后始终使用 awaitTermination c>关闭:它总是有可能你的任务卡住/死锁,用户会永远等待。
  • MyTask is an interface with function execute.
  • While stopping ScheduledExecutorService, Always use awaitTermination after invoking shutdown on it: There's always a likelihood your task is stuck / deadlocking and the user would wait forever.

我之前给Calender的例子只是一个想法我提到过,我避免了精确的时间计算和夏令时问题。根据@PaddyD

The previous example I gave with Calender was just an idea which I did mention, I avoided exact time calculation and Daylight saving issues. Updated the solution on per the complain of @PaddyD

更多推荐

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

本文发布于:2023-11-27 14:27:08,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1638450.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何使用   时间   在特定   ScheduledExecutorService

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!