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

标签 multithreading jakarta-ee servlets background-process scheduledexecutorservice

我正在使用 Java,我想在我的应用程序中持续运行一个 servlet,但我不知道如何去做。我的 servlet 有一种方法可以每天从数据库中获取用户计数以及整个数据库中的用户总数。所以我想让 servlet 为此持续运行。

最佳答案

你的问题是你误解了 servlet 的目的.它旨在处理 HTTP 请求,仅此而已。您只需要一个每天运行一次的后台任务。

EJB 可用吗?使用 @Schedule

如果您的环境碰巧支持 EJB(即真正的 Java EE 服务器,例如 WildFly、JBoss、TomEE、Payara、GlassFish 等),那么使用 @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 服务器,而是准系统 servletcontainer,例如 Tomcat、Jetty 等),则使用 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/48715701/

相关文章:

jakarta-ee - weblogic 是否支持 CDI Beans?

java - 当 glassfish Web 容器中的 servlet 使用时,我如何知道 FileWriter 实例保存我的文件的位置

java - Spring 3.2 中 View Body 不显示

Android 如何在不同线程中运行服务

python - Python multiprocessing.Queue 线程安全吗?

jakarta-ee - MDB 和 JMS 之间的区别

JavaScript 在 Maximo 中强制执行 OnChange

java - 同步性能

linux - mmap 是原子的吗?

java - 使用 DAO 模式将数据插入 hsqldb