这个问题已经在这里有一个答案:
- 如何运行在基于Servlet的Web应用程序的后台任务? 5个回答
我使用的Apache Tomcat JSP / Servlet的。 我要运行的方法每次10分钟。 我怎样才能做到这一点?
这个问题已经在这里有一个答案:
我使用的Apache Tomcat JSP / Servlet的。 我要运行的方法每次10分钟。 我怎样才能做到这一点?
正如你在Tomcat中,这仅仅是一个准系统servletcontainer,您不能使用EJB的@Schedule
这是由Java EE规范建议。 最好的办法是那么ScheduledExecutorService
从Java 1.5的java.util.concurrent
包。 您可以通过帮助触发此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.
}
}
如果您实际上使用与EJB支持和所有他们一个真正的Java EE容器(比如GlassFish,JBoss AS中,TomEE,等等),那么你可以使用@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准系统servletcontainer另一种选择呢。
需要注意的是,你不应该使用一个Timer
在所谓的“长寿命”运行的Java EE Web应用程序。 它有这使得它不适合于Java EE的(转引自使用以下主要问题在实践中的Java并发 ):
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();
}
}
此外,您可以尝试使用Java 定时器从ServletContextListener来 ,但它不是在一个Java EE容器推荐的,因为它需要远离容器线程资源的控制。 (与ScheduledExecutorService的第一个选项是要走的路)。
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);
而MyTask
实现TimerTask
是实现了一类Runnable
,所以你必须重写你的代码的run方法接口:
class MyTask extends TimerTask
{
public void run()
{
// your code here
}
}