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

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

问题描述

我在 Apache Tomcat 上使用 JSP/Servlet.我必须每 10 分钟运行一次方法.我怎样才能做到这一点?

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

推荐答案

由于您使用的是 Tomcat,它只是一个准系统的 servletcontainer,因此您不能为此使用 EJB 的 @ScheduleJava EE 规范推荐.那么你最好的选择是 ScheduledExecutorService 来自 Java 1.5 的 java.util.concurrent 包.您可以在 ServletContextListener 的帮助下触发此操作如下:

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

}

SomeTask 类如下所示:

public class SomeTask implements Runnable {

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

}

如果您实际上使用的是具有 EJB 支持的真正 Java EE 容器,并且所有这些容器都在 em(如 Glassfish、JBoss AS、TomEE 等),那么您可以使用 @Singleton 带有 @Schedule 方法.这样容器就会担心池化和销毁线程.您所需要的只是以下 EJB:

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.
    }

} 

请注意,通过这种方式,您可以继续以通常的方式(@PersistenceContext 等)透明地使用容器管理的事务,而 ScheduledExecutorService 则无法做到这一点 —您必须手动获取实体管理器并手动启动/提交/结束事务,但默认情况下,您在像 Tomcat 这样的准系统 servletcontainer 上已经没有其他选项了.

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.

请注意,在所谓的终生"运行 Java EE Web 应用程序中,永远不要使用 Timer.它存在以下主要问题,使其不适合在 Java EE 中使用(引自 Java 并发实践):

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 对系统时钟的变化很敏感,ScheduledExecutorService 不是.
  • Timer 只有一个执行线程,所以长时间运行的任务会延迟其他任务.ScheduledExecutorService 可以配置任意数量的线程.
  • TimerTask 中抛出的任何运行时异常都会杀死该线程,从而使 Timer 死亡,即计划任务将不再运行(直到您重新启动服务器).ScheduledThreadExecutor 不仅可以捕获运行时异常,还可以让您根据需要处理它们.抛出异常的任务将被取消,但其他任务将继续运行.
  • 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天全站免登陆