如何以固定的时间间隔运行后台作业方法? [英] How to run a background job method at fixed intervals?

查看:208
本文介绍了如何以固定的时间间隔运行后台作业方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Apache Tomcat上使用JSP / Servlet。我必须每10分钟运行一次方法。我怎样才能实现这个目标?

解决方案

当你在Tomcat上时,你只能是一个准系统的servlet容器,你不能使用它EJB的 @Schedule ,这是Java EE规范推荐的。您最好的选择是 ScheduledExecutorService java.util.concurrent 包的c $ c> 。您可以借助 ServletContextListener 如下所示:

  @WebListener 
公共类BackgroundJobManager实现ServletContextListener {

private ScheduledExecutorService调度程序;

@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 类看起来像这样:

 公共类SomeTask实现Runnable {

@Override
public void run(){
//在这里做你的工作。
}

}

如果您实际使用的是真实的具有EJB支持的Java EE容器和所有on em(如Glassfish,JBoss AS,TomEE等),然后您可以使用 @Singleton 带有 @Schedule 方法。这样容器就会担心汇集和销毁线程。您只需要以下EJB:

  @Singleton 
公共类SomeTask {

@Schedule(小时=*,分钟=* / 10,秒=0,持久=假)
public void run(){
//在这里做你的工作。
}

}

请注意,这样你就可以继续以通常的方式透明地使用容器管理的事务( @PersistenceContext 等等),这对于 ScheduledExecutorService &mdash是不可能的;你必须手动获取实体管理器并手动启动/提交/结束事务,但你默认情况下已经没有像Tomcat这样的准系统servlet容器上有另一个选项。



<请注意,在所谓的终身长期运行的Java EE Web应用程序中,绝不应使用 Timer 。它有以下主要问题,使其不适合在Java EE中使用(引自 Java Concurrency in Practice ):




  • 计时器对系统时钟的变化很敏感, ScheduledExecutorService 不是。

  • 计时器只有一个执行线程,因此长时间运行的任务可以延迟其他任务。 ScheduledExecutorService 可配置任意数量的线程。

  • TimerTask中抛出的任何运行时异常杀死一个线程,从而使 Timer 死亡,即计划任务将不再运行(直到你重新启动服务器)。 ScheduledThreadExecutor 不仅可以捕获运行时异常,还可以根据需要处理它们。抛出异常的任务将被取消,但其他任务将继续运行。


I am using JSP/Servlet on Apache Tomcat. I have to run a method every 10 minutes. How can I achieve this?

解决方案

As you're on Tomcat, which is just a barebones servletcontainer, you can't use EJB's @Schedule for this which is recommended by Java EE specification. Your best bet is then the ScheduledExecutorService from Java 1.5's java.util.concurrent package. You can trigger this with help of a ServletContextListener like follows:

@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();
    }

}

where the SomeTask class look like this:

public class SomeTask implements Runnable {

    @Override
    public void run() {
        // Do your job here.
    }

}

If you were actually using a real Java EE container with EJB support and all on em (like Glassfish, JBoss AS, TomEE, etc), then you could use a @Singleton EJB with a @Schedule method. This way the container will worry itself about pooling and destroying threads. All you need is then the following EJB:

@Singleton
public class SomeTask {

    @Schedule(hour="*", minute="*/10", second="0", persistent=false)
    public void run() {
        // Do your job here.
    }

} 

Note that this way you can continue transparently using container managed transactions the usual way (@PersistenceContext and so on), which isn't possible with ScheduledExecutorService — you'd have to manually obtain the entity manager and manually start/commit/end transaction, but you would by default already not have another option on a barebones servletcontainer like Tomcat anyway.

Note that you should never use a Timer in a supposedly "lifetime long" running Java EE web application. It has the following major problems which makes it unsuitable for use in Java EE (quoted from Java Concurrency in Practice):

  • Timer is sensitive to changes in the system clock, ScheduledExecutorService isn't.
  • Timer has only one execution thread, so long-running task can delay other tasks. ScheduledExecutorService can be configured with any number of threads.
  • Any runtime exceptions thrown in a TimerTask kill that one thread, thus making Timer dead, i.e. scheduled tasks will not run anymore (until you restart the server). ScheduledThreadExecutor not only catches runtime exceptions, but it lets you handle them if you want. Task which threw exception will be canceled, but other tasks will continue to run.

这篇关于如何以固定的时间间隔运行后台作业方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆