tomcat上的线程关闭钩子

dw1jzc5e  于 2021-10-10  发布在  Java
关注(0)|答案(1)|浏览(402)

我目前正在servlet类中启动一些线程,如下所示:

public class GTCInitServlet extends HttpServlet implements Runnable {

    public GTCInitServlet() {
        super();
    }

    public void init(ServletConfig config) throws ServletException {

        .
        .
        .
        .

        // Start ATC initialisation and then return so server is not blocked
        new Thread(this).start();       
    }

    public void run() {

        try {

            .
            .
            .
            Somne thread code
            .
            .
            .

            // Create ATC instance to force initialisation
            new GtcTypeController(gtcType);

            // Assume all is OK
            GtcInit.setReturnMessage(gtcType, "Initialization status = OK");    

        } catch (Throwable t) {

            GtcInit.setThrowable(gtcType, t);
            GtcInit.setReturnMessage(gtcType, t.getMessage());
        }
    }

    .
    .
    .
    .

    /**
     * Override javax.servlet.GenericServlet#destroy()
     */
    public void destroy() {
        super.destroy();
    }
}

当我关闭tomcat时,有很多线程保持打开状态。在tomcat日志中,我看到如下消息:

15-Jun-2021 01:05:53.302 WARNING [Catalina-utility-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [GTC] appears to have started a thread named [RequestListScheduler] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
 java.util.concurrent.PriorityBlockingQueue.take(PriorityBlockingQueue.java:549)
 com.att.logicalprovisioning.atc.RequestListScheduler.getNextRequestTarget(RequestListScheduler.java:97)
 com.att.logicalprovisioning.atc.RequestListScheduler.run(RequestListScheduler.java:51)

我在谷歌上搜索了一些关于tomcat完全关闭的信息,偶然发现了关闭挂钩。但我看到的大多数例子都是关于servletcontextlistener的。当我扩展httpservlet时,有没有办法做到这一点?
任何指示都会有帮助。

ecbunoof

ecbunoof1#

servlet不应丢失对创建线程的对象的引用。
因为servlet创建了一个 GtcTypeController ,这将启动一个 RequestListScheduler ,则应在servlet中保存第一个的引用:

synchronized (this) {
    this.gtcTypeController = new GtcTypeController(gtcType);
}

并实现一个方法(让我们调用它 GtcTypeController#destroy() ),它将被调用以停止 RequestListScheduler . 所以你 GTCInitServlet 应该是这样的:

@Override
public void destroy() {
    synchronized (this) {
        if (gtcTypeController != null) {
            gtcTypeController.destroy();
        } else {
            // You should also deal with the case when the anonymous
            // Thread started in `init()` didn't exit yet. This happens, when `init()` and
            // `destroy()` are called in a rapid sequence()
        }
    }
}

相关问题