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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4691132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:12:13  来源:igfitidea点击:

How to run a background task in a servlet based web application?

multithreadingjakarta-eeservletsbackground-processscheduledexecutorservice

提问by pritsag

I'm using Java and I want to keep a servlet continuously running in my application, but I'm not getting how to do it. My servlet has a method which gives counts of the user from a database on a daily basis as well as the total count of the users from the whole database. So I want to keep the servlet continuously running for that.

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

回答by BalusC

Your problem is that you misunderstand the purpose of the servlet. It's intented to act on HTTP requests, nothing more. You want just a background task which runs once on daily basis.

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

EJB available? Use @Schedule

EJB 可用吗?用@Schedule

If your environment happen to support EJB (i.e. a real Java EE server such as WildFly, JBoss, TomEE, Payara, GlassFish, etc), then use @Scheduleinstead. Here are some examples:

如果您的环境恰好支持 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.
    }

} 

Yes, that's really all. The container will automatically pickup and manage it.

是的,仅此而已。容器将自动提取和管理它。

EJB unavailable? Use ScheduledExecutorService

EJB 不可用?用ScheduledExecutorService

If your environment doesn't support EJB (i.e. you're not using not a real Java EE server, but a barebones servletcontainer such as Tomcat, Jetty, etc), then use ScheduledExecutorService. This can be initiated by a ServletContextListener. Here's a kickoff example:

如果您的环境不支持 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();
    }

}

Where the job classes look like this:

工作类如下所示:

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

}

Do not ever think about using java.util.Timer/java.lang.Threadin a Java EE / Servlet based environment

永远不要考虑在基于 Java EE / Servlet 的环境中使用java.util.Timer/java.lang.Thread

Last but not least, neverdirectly use java.util.Timerand/or java.lang.Threadin Java EE. This is recipe for trouble. An elaborate explanation can be found in this JSF-related answer on the same question: Spawning threads in a JSF managed bean for scheduled tasks using a timer.

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

回答by Twister

I would suggest using a library like quartz in order to run the task at regular intervals. What does the servlet really do ? It sends you a report ?

我建议使用像quartz 这样的库来定期运行任务。servlet 到底有什么作用?它会向您发送报告吗?

回答by Ali Alimohammadi

Implement two classes and call startTask()in main.

实行两班,并呼吁startTask()main

public void startTask()
{
    // Create a Runnable
    Runnable task = new Runnable() {
        public void run() {
            while (true) {
                runTask();
            }
        }
    };

    // Run the task in a background thread
    Thread backgroundThread = new Thread(task);
    // Terminate the running thread if the application exits
    backgroundThread.setDaemon(true);
    // Start the thread
    backgroundThread.start();
}

public void runTask()
{
    try {
        // do something...         
        Thread.sleep(1000);

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

回答by Jeryl Cook

In a production system that may have multiple non-jee containers running. Use anot enterprise scheduler like Quartz scheduler which can be configured to use a database for task maamgememt.

在可能有多个非 jee 容器运行的生产系统中。使用类似 Quartz 调度器这样的企业调度器,它可以配置为使用数据库来执行任务 maamgememt。