加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 在停止Tomcat时,ExecutorService不会从contextDestroye

发布时间:2020-12-15 01:06:40 所属栏目:Java 来源:网络整理
导读:我有一个ExecutorService executor = Executors.newSingleThreadExecutor();我想在服务器关闭时停止. 我有一个实现ServletContextListener的类,它用@WebListener注释. 我在该课程中有两种方法: @Overridepublic void contextInitialized(ServletContextEven

我有一个ExecutorService executor = Executors.newSingleThreadExecutor();我想在服务器关闭时停止.

我有一个实现ServletContextListener的类,它用@WebListener注释.

我在该课程中有两种方法:

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    System.out.println("ServletContextListener started");
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    executor.shutdown();
    executor.shutdownNow();
    System.out.println("ServletContextListener destroyed");
}

而且我看到它在它们应该的时候打印出它们中的内容,但是当我在intelij中按下一次停止按钮时,我得到:

SEVERE: The web application [] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak.

在它打印出ServletContextListener之后就被销毁了.

我需要再次按下停止按钮才能完全停止它.

为什么它不会关闭ExecutorService,即使它到达executor.shutdown();?我究竟做错了什么?

PS:这是我唯一的ExecutorService,没有其他线程由我制作.

EDIT2:

执行程序服务是单例类中的一个字段,它使用类初始化:

private ExecutorService executor = Executors.newSingleThreadExecutor();

这是类的初始化方式(延迟初始化):

public static RoomsManager getRoomsManager(ServletContext servletContext) {
    if (servletContext.getAttribute(MANAGER_GAMES_ATTRIBUTE_NAME) == null) {
        servletContext.setAttribute(MANAGER_GAMES_ATTRIBUTE_NAME,new RoomsManager());
    }
    return (RoomsManager)servletContext.getAttribute(MANAGER_GAMES_ATTRIBUTE_NAME);
}

并注释如下:

@WebListener
public class RoomsManager  implements ServletContextListener {

停止按钮是intelij IDEA中播放和调试按钮附近的红色方块.

最佳答案
问题是你有两个不同的RoomsManager实例(因此有两个不同的执行器):第一个是由Tomcat创建的,第二个是由你创建的.

当您使用@WebListener注释RoomsManager时,Tomcat会自动创建该类的实例并订阅它以接收servlet上下文创建/销毁事件.该实例是实际停止其执行程序并打印ServletContextListener的实例.

第二个实例是由您在getRoomsManager方法中创建的(顺便说一下,该方法看起来不是线程安全的).该实例未在Tomcat中注册,并且未接收servlet上下文“destroy”事件,因此它甚至不会尝试关闭其执行程序.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读