multithreading - studio - programas con hilos en java
¿Cómo ejecutar una tarea en segundo plano en una aplicación web basada en servlet? (5)
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.
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.
Implementa dos clases y llama a 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();
}
}
Puede usar cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php
Sugiero usar una biblioteca como el cuarzo para ejecutar la tarea a intervalos regulares. ¿Qué hace realmente el servlet? Te envía un informe?
Tu problema es que no entiendes 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? Use @Schedule
Si su entorno es compatible con EJB (por ejemplo, WildFly, JBoss AS / EAP, TomEE, GlassFish, etc.), utilice @Schedule
en @Schedule
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? Use ScheduledExecutorService
Si su entorno no es compatible con EJB (es decir, no es un servidor Java EE real, por ejemplo, Tomcat, Jetty, etc.), utilice 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.
}
}
No pienses nunca 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: Enhebrar hilos en un bean gestionado JSF para tareas programadas usando un temporizador .