线程的 Tomcat 上的 ShutdownHooks
ShutdownHooks on Tomcat for Threads
我目前正在 Servlet class 中启动一些线程,如下所示:
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)
我在 Google 上搜索了一些有关彻底关闭 Tomcat 的信息,我偶然发现了关闭挂钩。但我看到的大多数示例都是使用 ServletContextListener 的。当我扩展 HttpServlet 时有什么办法吗?
任何指示都会有所帮助。
您的 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()
}
}
}
我目前正在 Servlet class 中启动一些线程,如下所示:
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)
我在 Google 上搜索了一些有关彻底关闭 Tomcat 的信息,我偶然发现了关闭挂钩。但我看到的大多数示例都是使用 ServletContextListener 的。当我扩展 HttpServlet 时有什么办法吗?
任何指示都会有所帮助。
您的 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()
}
}
}