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

时间:2011-01-14 12:39:46

标签: multithreading java-ee servlets background-process scheduledexecutorservice

我正在使用Java,我希望在我的应用程序中保持servlet不断运行,但我不知道该怎么做。我的servlet有一个方法,它每天从数据库中提供用户的计数以及整个数据库中用户的总数。所以我想让servlet继续为此运行。

4 个答案:

答案 0 :(得分:194)

你的问题是你误解了servlet的目的。它的目的是对HTTP请求采取行动,仅此而已。您只需要一个每天运行一次的后台任务。

EJB可用吗?使用@Schedule

如果您的环境恰好支持EJB(例如WildFly,JBoss AS / EAP,TomEE,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.
    }

} 

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

EJB不可用?使用ScheduledExecutorService

如果您的环境不支持EJB(即不是真正的Java EE服务器,例如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);
    }

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

}

不要考虑在Java EE中使用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

答案 1 :(得分:4)

我建议使用像石英这样的库,以便定期运行任务。 servlet真正做了什么?它会向您发送报告吗?

答案 2 :(得分:3)

实施两个课程并在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();
    }
}

答案 3 :(得分:2)