如何使用 scheduledexecutorservice 强制创建单个线程并避免多线程



当我进入欢迎.jsp页面时,我只想执行一次以下 JAVA 代码。

欢迎光临.jsp:

<%WeeklyScheduledMail wsm = WeeklyScheduledMail.INSTANCE;
wsm.startThread(); %>

因此,如果用户在服务器启动后访问网站,则该代码可以使用一次,而登录并访问欢迎的其他用户.jsp将不会执行该 JAVA 代码。

首先,我尝试使用枚举实现单例模式,我认为这就足够了,但它不起作用。我还尝试了这些方法的同步关键字,但什么都没有......

我确定我做错了什么,或者有更好的方法来做我想做的事情。

代码的某些部分:

每周定时邮件.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);          
}
}

任务发送电子邮件.java:

public class TaskSendEmail implements Runnable{
public void run() {
System.out.println("Hello: "+System.currentTimeMillis());
}
}

您正在研究运行应用程序初始化代码的错误概念。向用户公开的 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>

上面的代码和配置将导致您的计划在应用程序启动时运行一次。

最新更新