Как заставить создать один поток, используя scheduledexecutorservice и избежать многопоточности
Я хотел бы выполнить следующий код JAVA только один раз при входе на страницу welcome.jsp.
welcome.jsp:
<%WeeklyScheduledMail wsm = WeeklyScheduledMail.INSTANCE;
wsm.startThread(); %>
Таким образом, если пользователь получает доступ к веб-сайту после запуска сервера, этот код можно использовать один раз, и другие пользователи, которые входят в систему и получают доступ к welcome.jsp, не будут выполнять этот код JAVA.
Сначала я попытался реализовать шаблон Singleton с помощью enum, я подумал, что этого будет достаточно, но это не сработало. Я также попробовал ключевое слово Synchronized для методов, но ничего...
Я уверен, что я сделал что-то не так, или есть лучший способ сделать то, что я хочу сделать.
Некоторые части кода:
WeeklyScheduledMail.java:
public enum WeeklyScheduledMail{
INSTANCE;
public void startThread() {
ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
Runnable task = new TaskSendEmail();
int initialDelay = 0;
int periodicDelay = 10;
scheduler.scheduleAtFixedRate(task, initialDelay, periodicDelay,
TimeUnit.SECONDS);
}
}
TaskSendEmail.java:
public class TaskSendEmail implements Runnable{
public void run() {
System.out.println("Hello: "+System.currentTimeMillis());
}
}
1 ответ
Вы ищете неправильную концепцию для запуска кода инициализации приложения. JSP и другие ресурсы, предоставляемые пользователю, не предназначены для этого. Даже если вы можете принудительно использовать ленивую логику инициализации, все равно можно избежать накладных расходов.
То, что вы ищете, предоставляется JavaEE: слушатель контекста, который вызывается один раз при запуске приложения, чтобы уведомить ваше приложение о том, что контекст был инициализирован:
public class MyContextListener implements javax.servlet.ServletContextListener {
private static fWeeklyScheduledMail wsm =
weeklyScheduledMail.INSTANCE;
@Override
public void contextInitialized(ServletContextEvent sce) {
wsm.startThread();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
wsm.stopThread();
}
}
Этот слушатель должен быть зарегистрирован в web.xml
дескриптор развертывания (под web-app
):
<listener>
<listener-class>my.packg.MyContextListener</listener-class>
</listener>
Приведенный выше код и конфигурация приведут к запуску вашего расписания один раз при запуске приложения.