我正在尝试每周运行一次方法。例如,每个星期一晚上8点。我使用此代码:
Timer timer = new Timer();
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
Date time = calendar.getTime();
timer.schedule(new PrintTask(),
time);
// other code where variable gets increased
public class PrintTask extends TimerTask {
public void run() {
variable = 0;
}
}
但是,如果我是对的,只要日历时间已经过去,dosomething
代码就会连续运行。例如,现在已经是星期一,因此dosomething
代码始终运行。 variabele增加,但必须在星期一将其重置为0。该变量现在始终为0,因为它会一次又一次地重置。如果使用calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
,则该变量不会重置,因为尚未到周日。但是,一旦到了周日晚上8点,他可能会继续重置当天的其余时间。
我希望dosomething
代码在指定的一次仅执行一次。有人可以告诉我如何调整代码以实现此目标吗?
对不起,我的英语
[请在此处查看此问题(How i can run my TimerTask everyday 2 PM)。它几乎处理相同的问题。
使用Timer类的cancel api取消计时器,并在run()方法中重新安排计时器;这应该防止每次都更新变量。
Timer类可用于安排事物运行一次或多次。此时的调度方式只会在给定的时间进行一次。
如果要安排任务,则有更好的选择,例如ScheduledExecutorService:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
根据实践中的Java并发性:
- 计时器可能对系统时钟的变化敏感,ScheduledThreadPoolExecutor则不敏感。
- 计时器只有一个执行线程,因此长时间运行的任务可能会延迟其他任务。 ScheduledThreadPoolExecutor可以配置为任何数量的线程。此外,您可以完全控制创建线程(如果需要)(通过提供ThreadFactory)。
- 在TimerTask中抛出的运行时异常会杀死该线程,从而使Timer失效:-( ...,即,计划任务将不再运行。ScheduledThreadExecutor不仅捕获运行时异常,而且还捕获使您可以根据需要处理它们(通过重写afterExecute方法来自ThreadPoolExecutor)。抛出异常的任务将被取消,但其他任务将继续运行。