我需要在一天的特定时间运行一个可调用的。一种方法是计算now和所需时间之间的timediff,并使用executor.scheduleAtFixedRate。
有更好的主意吗?
executor.scheduleAtFixedRate(command, TIMEDIFF(now,run_time), period, TimeUnit.SECONDS))
答案 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
);
}
}