multithreading - 如何在基于servlet的Web应用程序中运行后台任务?

标签 multithreading jakarta-ee servlets background-process scheduledexecutorservice

我正在使用Java,但我想保持servlet在我的应用程序中连续运行,但是我没有得到如何做的信息。我的servlet有一种方法,可以每天提供数据库中用户的数量以及整个数据库中用户的总数。因此,我想为此继续保持servlet的运行。

最佳答案

您的问题是您误解了servlet的目的。它旨在对HTTP请求执行操作,仅此而已。您只需要每天执行一次的后台任务。

EJB可用吗?使用@Schedule
如果您的环境碰巧支持EJB(即WildFly,JBoss,TomEE,Payara,GlassFish等真正的Java EE服务器),请改用 @Schedule 。这里有些例子:

@Singleton
public class BackgroundJobManager {

    @Schedule(hour="0", minute="0", second="0", persistent=false)
    public void someDailyJob() {
        // Do your job here which should run every start of day.
    }

    @Schedule(hour="*/1", minute="0", second="0", persistent=false)
    public void someHourlyJob() {
        // Do your job here which should run every hour of day.
    }

    @Schedule(hour="*", minute="*/15", second="0", persistent=false)
    public void someQuarterlyJob() {
        // Do your job here which should run every 15 minute of hour.
    }

    @Schedule(hour="*", minute="*", second="*/5", persistent=false)
    public void someFiveSecondelyJob() {
        // Do your job here which should run every 5 seconds.
    }

} 

是的,这就是全部。容器将自动进行拾取和管理。

EJB不可用?使用ScheduledExecutorService
如果您的环境不支持EJB(即您未使用的不是真正的Java EE服务器,而是使用了诸如Tomcat,Jetty等准系统的servlet容器),请使用 ScheduledExecutorService 。这可以由 ServletContextListener 启动。这是一个启动示例:
@WebListener
public class BackgroundJobManager implements ServletContextListener {

    private ScheduledExecutorService scheduler;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
        scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
        scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
        scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        scheduler.shutdownNow();
    }

}

作业类别如下所示:
public class SomeDailyJob implements Runnable {

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

}
public class SomeHourlyJob implements Runnable {

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

}
public class SomeQuarterlyJob implements Runnable {

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

}
public class SomeFiveSecondelyJob implements Runnable {

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

}

永远不要考虑在基于Java EE/Servlet的环境中使用java.util.Timer/java.lang.Thread
最后但并非最不重要的一点是,从不在Java EE中直接使用java.util.Timer和/或java.lang.Thread。这是麻烦的秘诀。在这个与JSF相关的答案中,可以找到对同一问题Spawning threads in a JSF managed bean for scheduled tasks using a timer的详尽解释。

关于multithreading - 如何在基于servlet的Web应用程序中运行后台任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63301779/

相关文章:

java - 为什么SynchronizedList的listIterator需要用户外部同步?

java - JPA 存储库应该首选哪个 CDI 范围

java - 是否可以使用 ANT 构建文件访问/添加远程位置 jar 到项目中?

Java 嵌入式 Web 界面

java - 如何获取运行我的 Web 应用程序的用户的 Windows 登录用户名?

c# - TaskScheduler - 执行延续

c# - 一个后台工作线程和多个进度条

.net - 为什么计时器线程上未处理的异常不会使进程崩溃

jakarta-ee - org.jboss.weld.exceptions.IllegalStateException : WELD-000227 after every change in code

java - 登录和注销的误区