Как заставить создать один поток, используя 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>

Приведенный выше код и конфигурация приведут к запуску вашего расписания один раз при запуске приложения.

Другие вопросы по тегам