Ваша проблема полягає в тому, що ви неправильно розумієте призначення сервлета . Він призначений діяти за запитами 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, а базовий контейнер сервлет-контейнера, такий як Tomcat, Jetty тощо), тоді використовуйте ScheduledExecutorService
. Це може ініціювати a 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.util.Timer
/ java.lang.Thread
в середовищі Java EE / Servlet
І останнє, але не менш важливе, ніколи не використовуйте безпосередньо java.util.Timer
та / або java.lang.Thread
в Java EE. Це рецепт неприємностей. Розгорнуте пояснення можна знайти в цій відповіді на те саме питання, що стосується JSF : Нерест потоків у керованому файлі JSF для запланованих завдань за допомогою таймера .