问题
I need to run a callable at a specific time of day. One way to do it is to calculate the timediff between now and the desired time , and to use the executor.scheduleAtFixedRate .
Have a better idea?
executor.scheduleAtFixedRate(command, TIMEDIFF(now,run_time), period, TimeUnit.SECONDS))
回答1:
For this kind of thing, just go ahead and install Quartz. EJB has some support for this kind of thing but really you just want Quartz for scheduled tasks.
That being said, if you insist on doing it yourself (and I'd recommend not), use the ScheduledThreadPoolExecutor.
ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(4);
ScheduledFuture<?> future =
executor.scheduleAtFixedRate(runnable, 1, 24, TimeUnit.HOUR);
which will run the Runnable
every day with an initial delay of one hour.
Or:
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
has a somewhat simpler interface and was introduced in 1.3 (the other is 1.5) but a single thread executes all tasks whereas the first one allows you to configure that. Plus ScheduledExecutorService
has nicer shutdown (and other) methods.
回答2:
I would recommend using Quartz Framework. This will allow you to schedule jobs in a cron like fashion.
回答3:
You can user JDK Timer and dont need to calculate the time difference:
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);
回答4:
Quartz is a great idea, but might be a bit of overkill depending on what you need. I think youre real issue is trying to cram your service into a servlet, when you aren't actually listening to incoming HttpServletRequests. Instead, consider using a ServletContextListener to start up your service, and a Timer, as Maurice suggested:
web.xml:
<listener>
<listener-class>com.myCompany.MyListener</listener-class>
</listener>
And then your class looks like this:
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
);
}
}
来源:https://stackoverflow.com/questions/438312/how-to-schedule-a-callable-to-run-on-a-specific-time