我正在使用Apache Tomcat上的JSP/Servlet技术。我需要每10分钟运行一次一个方法。请问如何实现?
我正在使用Apache Tomcat上的JSP/Servlet技术。我需要每10分钟运行一次一个方法。请问如何实现?
由于您正在使用Tomcat,它只是一个基本的servlet容器,因此您无法使用Java EE规范推荐的EJB的@Schedule
。您最好使用Java 1.5的java.util.concurrent
包中的ScheduledExecutorService
。您可以通过ServletContextListener
触发它,如下所示:
@WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
@Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeTask(), 0, 10, TimeUnit.MINUTES);
}
@Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
其中SomeTask
类看起来像这样:
public class SomeTask implements Runnable {
@Override
public void run() {
// Do your job here.
}
}
@Singleton
EJB和@Schedule
方法。这样,容器将自动处理线程池和销毁线程。您所需要的就是以下EJB:@Singleton
public class SomeTask {
@Schedule(hour="*", minute="*/10", second="0", persistent=false)
public void run() {
// Do your job here.
}
}
@PersistenceContext
等)透明地使用容器管理的事务,但是这在ScheduledExecutorService
中是不可能的 - 您必须手动获取实体管理器并手动启动/提交/结束事务,但是在像Tomcat这样的基本servlet容器上,您默认情况下已经没有其他选择。 Timer
。 它具有以下主要问题,使其不适用于Java EE(引用自Java Concurrency in Practice):
Timer
对系统时钟的变化比较敏感,ScheduledExecutorService
则不是。Timer
只有一个执行线程,因此长时间运行的任务可能会延迟其他任务。 ScheduledExecutorService
可以配置任意数量的线程。TimerTask
中抛出的任何运行时异常都会终止该线程,因此使 Timer
失效,即预定的任务将不再运行(直到重新启动服务器)。 ScheduledThreadExecutor
不仅捕获运行时异常,而且如果需要还可以让您处理它们。引发异常的任务将被取消,但其他任务将继续运行。请阅读ScheduledExecutorService,它必须由ServletContextListener初始化。
public class MyContext implements ServletContextListener
{
private ScheduledExecutorService sched;
@Override
public void contextInitialized(ServletContextEvent event)
{
sched = Executors.newSingleThreadScheduledExecutor();
sched.scheduleAtFixedRate(new MyTask(), 0, 10, TimeUnit.MINUTES);
}
@Override
public void contextDestroyed(ServletContextEvent event)
{
sched.shutdownNow();
}
}
Timer timer = new Timer("MyTimer");
MyTask t = new MyTask();
//Second Parameter is the specified the Starting Time for your timer in
//MilliSeconds or Date
//Third Parameter is the specified the Period between consecutive
//calling for the method.
timer.schedule(t, 0, 1000*60*10);
实现TimerTask
的MyTask
是一个实现Runnable
接口的类,所以您需要使用您的代码重写run方法:
class MyTask extends TimerTask
{
public void run()
{
// your code here
}
}
Timer
。 - BalusC