java - 如何以固定的时间间隔运行后台作业方法?

标签 java jakarta-ee tomcat servlets background-process

<分区>

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

最佳答案

因为你在 Tomcat 上,它只是一个准系统 servlet 容器,你不能为此使用 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.
    }

}

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

@Singleton
public class SomeTask {

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

} 

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

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

  • Timer 对系统时钟的变化很敏感,ScheduledExecutorService 则不然。
  • Timer 只有一个执行线程,所以长时间运行的任务可以延迟其他任务。 ScheduledExecutorService 可以配置任意数量的线程。
  • TimerTask 中抛出的任何运行时异常都会杀死那个线程,从而使 Timer 死掉,即计划的任务将不再运行(直到您重新启动服务器)。 ScheduledThreadExecutor 不仅可以捕获运行时异常,还可以根据需要处理它们。抛出异常的任务将被取消,但其他任务将继续运行。

关于java - 如何以固定的时间间隔运行后台作业方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15787605/

相关文章:

java - 类似于 Java 的 OpenCart

Java 类不会导入到 .jsp 文件

java - Tomcat - 从命令行覆盖 catalina.properties

Hibernate 花费太多时间并执行一些神秘的操作..

java - 将运行时(元)数据传递给 CDI 中的生产者方法

java - 用于部署用 Java 编写的分层业务应用程序的模式

java - 如何根据定义的大小将数据框中的一列拆分为多列

java - Java 是否隐式通知等待线程?

java - 如何消除使用 dom4j Iterator 时未经检查的分配警告

java - Maven 存储库 Artifact : jboss-j2ee