Java 如何计算ScheduledExecutorService#scheduleAtFixedRate的初始延迟

Java 如何计算ScheduledExecutorService#scheduleAtFixedRate的初始延迟,java,scheduled-tasks,java-7,Java,Scheduled Tasks,Java 7,我想在一个特定的时间运行一个任务,比如每天晚上7点11分。 我尝试了下面的代码,但它不起作用 import java.util.Calendar; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Task3 {

我想在一个特定的时间运行一个任务,比如每天晚上7点11分。 我尝试了下面的代码,但它不起作用

import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Task3 {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                System.out.println(new Date());
                System.out.println("Hello !!");
            }
        };

        Calendar calendar = Calendar.getInstance();
        long now = calendar.getTimeInMillis();
        calendar.set(Calendar.HOUR, 18);
        calendar.set(Calendar.MINUTE, 11);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        service.scheduleAtFixedRate(runnable, calendar.getTimeInMillis(), 5, TimeUnit.SECONDS);
    }
}
在上面的代码中,我尝试从每天晚上7:11以5秒的间隔运行调度任务。但它的行为并不像我预期的那样。另外,如果我想在另一个条件下做同样的事情,任务应该只在特定的日子执行,比如说每周二和周三


我在计算方法的initialDelay参数时是否犯了某种错误?

旁注:使用特殊库(如quartz)可能更简单

initialDelay
参数给出运行任务之前要等待的时间单位数。在您的情况下,您需要计算到7:11的剩余时间

所以它可能看起来像:

long nextRun = calendar.getTimeInMillis();
long initialDelayMillis = nextRun - now;
long oneDayMillis = 1000L * 60 * 60 * 24;
service.scheduleAtFixedRate(runnable, initialDelayMillis, oneDayMillis, TimeUnit.MILLISECONDS);
但这只会处理基本情况。特别是它根本不会处理时钟调整或DST。说“只在星期二和星期五”并不容易


另一种方法是只安排下一次运行,并在runnable结束时重新安排。这样,您就可以更好地控制执行。但底线是:请看我最初的评论。

最好是ScheduledExecutor服务。 但也许也可以使用定时器。用于摆动另一个计时器

这里是一个示例(计时器和timerTask可以使用cancel/purge停止)

 import java.util.Calendar;
 import java.util.Date;
 import java.util.Timer;
 import java.util.TimerTask;

 public class TimeScheduleTest {
  Timer timer = new Timer();
  public static void main(String[] args) {
   new TimeScheduleTest().startApp();
  }

 private void startApp() {
  Calendar calendar = Calendar.getInstance();
  calendar.set(Calendar.DAY_OF_WEEK,Calendar.TUESDAY);
  calendar.set(Calendar.HOUR_OF_DAY, 7);
  calendar.set(Calendar.MINUTE, 11);
  calendar.set(Calendar.SECOND, 0);
  calendar.set(Calendar.MILLISECOND, 0);
  timer.scheduleAtFixedRate(new StartTimer(), calendar.getTime(), 5000);
 } 

 class StartTimer extends TimerTask {
  public void run() {
   System.out.println(new Date());
   System.out.println("Hello !!");
  }
 }
}