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

Java 如何以固定的时间间隔运行后台作业方法?,java,jakarta-ee,tomcat,servlets,background-process,Java,Jakarta Ee,Tomcat,Servlets,Background Process,我正在ApacheTomcat上使用JSP/Servlet。我必须每10分钟运行一次方法。我如何才能做到这一点?请阅读,它必须由 此外,您可以尝试从中使用Java,但不建议在JavaEE容器中使用,因为它会从容器中夺走对线程资源的控制。(使用ScheduledExecutorService的第一个选项是要走的路) 实现TimerTask的MyTask是一个实现Runnable接口的类,因此您必须用代码覆盖run方法: class MyTask extends TimerTask { pub

我正在ApacheTomcat上使用JSP/Servlet。我必须每10分钟运行一次方法。我如何才能做到这一点?

请阅读,它必须由

此外,您可以尝试从中使用Java,但不建议在JavaEE容器中使用,因为它会从容器中夺走对线程资源的控制。(使用ScheduledExecutorService的第一个选项是要走的路)

实现
TimerTask
MyTask
是一个实现
Runnable
接口的类,因此您必须用代码覆盖run方法:

class MyTask extends TimerTask 
{
  public void run() 
  { 
    // your code here
  }
}

由于您使用的是Tomcat,它只是一个基本的servletcontainer,所以不能使用EJB的
@Schedule
来实现这一点,这是JavaEE规范推荐的。最好的选择是来自Java1.5的
Java.util.concurrent
包。您可以通过以下类似的方法触发此操作:

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

}
如果您实际使用的是一个真正的JavaEE容器,它支持EJB,并且都在em上(如Glassfish、JBoss AS、TomEE等),那么您可以使用EJB和方法。这样,容器就会担心线程的池化和破坏。然后,您只需要以下EJB:

@Singleton
public class SomeTask {

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

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

请注意,在假定的“终生”运行的JavaEEWeb应用程序中,绝不应使用
计时器。它存在以下主要问题,不适合在Java EE中使用(引自):

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

  • 好的,我知道了,我知道了。但是从哪里我必须调用这个方法。我必须在我的申请启动后立即启动。谢谢@BalusC。我在回答中明确提到了这一点。回答很好,谢谢@BalusC。但有一个问题:如果我需要更改通话间隔,我将如何修改调度器?e、 g.我有一些“int frequency”,可以由用户在webgui中设置,它表示两次运行之间的时间(以秒为单位)。
    public class SomeTask implements Runnable {
    
        @Override
        public void run() {
            // Do your job here.
        }
    
    }
    
    @Singleton
    public class SomeTask {
    
        @Schedule(hour="*", minute="*/10", second="0", persistent=false)
        public void run() {
            // Do your job here.
        }
    
    }