Как запланировать запуск Callable в определенное время? - PullRequest
2 голосов
/ 13 января 2009

Мне нужно запустить вызываемый в определенное время суток. Один из способов сделать это - рассчитать разницу во времени между текущим и желаемым временем и использовать executor.scheduleAtFixedRate.

Есть идея получше?

executor.scheduleAtFixedRate(command, TIMEDIFF(now,run_time), period, TimeUnit.SECONDS))

Ответы [ 4 ]

11 голосов
/ 13 января 2009

Для такого рода вещей просто установите Кварц . EJB имеет некоторую поддержку для такого рода вещей, но на самом деле вы просто хотите Quartz для запланированных задач.

При этом, если вы настаиваете на том, чтобы сделать это самостоятельно (и я бы рекомендовал этого не делать), используйте ScheduledThreadPoolExecutor.

ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(4);
ScheduledFuture<?> future =
  executor.scheduleAtFixedRate(runnable, 1, 24, TimeUnit.HOUR);

, который будет запускать Runnable каждый день с начальной задержкой в ​​один час.

Или:

Timer timer = new Timer();
final Callable c = callable;
TimerTask task = new TimerTask() {
  public void run() {
    c.call();
  }
}
t.scheduleAtFixedRate(task, firstExecuteDate, 86400000); // every day

Timer имеет несколько более простой интерфейс и был введен в 1.3 (другой - 1.5), но один поток выполняет все задачи, тогда как первый позволяет вам это настроить. Плюс ScheduledExecutorService имеет более приятные (и другие) методы выключения.

1 голос
/ 13 мая 2009

Кварц - отличная идея, но может быть немного излишним в зависимости от того, что вам нужно. Я думаю, что вы действительно пытаетесь втиснуть свой сервис в сервлет, когда вы на самом деле не слушаете входящие HttpServletRequests. Вместо этого рассмотрите возможность использования ServletContextListener для запуска службы и таймера, как предложил Морис:

web.xml:

<listener>
  <listener-class>com.myCompany.MyListener</listener-class>
</listener>

И тогда ваш класс выглядит так:

public class MyListener implements ServletContextListener {

    /** the interval to wait per service call - 1 minute */
    private static final int INTERVAL = 60 * 60 * 1000;

    /** the interval to wait before starting up the service - 10 seconds */
    private static final int STARTUP_WAIT = 10 * 1000;

    private MyService service = new MyService();
    private Timer myTimer;

    public void contextDestroyed(ServletContextEvent sce) {
        service.shutdown();
        if (myTimer != null)
                myTimer.cancel();
    }

    public void contextInitialized(ServletContextEvent sce) {
        myTimer = new Timer();
        myTimer.schedule(new TimerTask() {
                public void run() {
                        myService.provideSomething();
                }
        },STARTUP_WAIT, INTERVAL
      );
    }
}
1 голос
/ 13 января 2009

Вы можете использовать JDK Timer , и вам не нужно рассчитывать разницу во времени:

Timer timer = new Timer();
Date executionDate = new Date();
long period = 24 * 60 * 60 * 1000;
timer.scheduleAtFixedRate(
    new TimerTask() {
        @Override
        public void run() {
            // the task
        }
    },
    executionDate,
    period);
1 голос
/ 13 января 2009

Я бы порекомендовал использовать Quartz Framework . Это позволит вам планировать работу в стиле cron.

...