Pregunta ¿Cómo ejecutar una tarea en segundo plano en una aplicación web basada en servlet?


Estoy usando Java y quiero mantener un servlet continuamente ejecutándose en mi aplicación, pero no estoy obteniendo cómo hacerlo. Mi servlet tiene un método que da cuenta del usuario de una base de datos a diario, así como el recuento total de los usuarios de toda la base de datos. Así que quiero mantener el servlet continuamente funcionando para eso.


76
2018-01-14 12:39


origen


Respuestas:


Tu problema es que malinterpretas el propósito del servlet. Está diseñado para actuar sobre solicitudes HTTP, nada más. Solo desea una tarea en segundo plano que se ejecuta una vez a diario.

EJB disponible? Utilizar @Schedule

Si su entorno es compatible con EJB (por ejemplo, WildFly, JBoss AS / EAP, TomEE, GlassFish, etc.), utilice @Schedule en lugar.

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

} 

Sí, eso es realmente todo. El contenedor lo recogerá y administrará automáticamente.

EJB no disponible? Utilizar ScheduledExecutorService

Si su entorno no es compatible con EJB (es decir, no es un servidor Java EE real, por ejemplo, Tomcat, Jetty, etc.), use ScheduledExecutorService. Esto puede ser iniciado por un ServletContextListener. Aquí hay un ejemplo de inicio:

@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();
    }

}

Donde las clases de trabajo se ven así:

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

}

Nunca pienses en usar java.util.Timer/java.lang.Thread en Java EE

Nunca use directamente java.util.Timer y / o java.lang.Thread en Java EE. Esta es la receta para problemas. Se puede encontrar una explicación elaborada en esta respuesta relacionada con JSF sobre la misma pregunta: Engendrar hilos en un frijol administrado JSF para tareas programadas usando un temporizador.


173
2018-01-14 13:45



Sugiero usar una biblioteca como el cuarzo para ejecutar la tarea a intervalos regulares. ¿Qué hace realmente el servlet? Te envía un informe?


3
2018-01-14 13:08



Puede usar cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php


1
2017-12-22 08:13



Implementar dos clases y llamar startTask() en 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();
    }
}

1
2018-03-05 17:49



En un sistema de producción que puede tener varios contenedores no jee en ejecución. Utilice un planificador empresarial anot como el programador de Quartz, que puede configurarse para usar una base de datos para el maamgememt de tareas.


0
2018-02-21 15:31