如何安排Callable在特定时间运行?

时间:2009-01-13 08:23:37

标签: java scheduling callable

我需要在一天的特定时间运行一个可调用的。一种方法是计算now和所需时间之间的timediff,并使用executor.scheduleAtFixedRate。

有更好的主意吗?

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

4 个答案:

答案 0 :(得分:11)

对于这种事情,请继续安装Quartz。 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 :(得分:1)

我建议使用Quartz Framework。这将允许您以类似时尚的方式安排工作。

答案 2 :(得分:1)

您可以使用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);

答案 3 :(得分:1)

Quartz是一个好主意,但根据您的需要可能会有点过分。我认为你真正的问题是当你实际上没有收听传入的HttpServletRequests时,试图将你的服务塞进一个servlet。相反,考虑使用ServletContextListener启动您的服务,以及一个Timer,正如Maurice建议的那样:

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