[英]Tomcat fails to stop thread in webapp
在我的webapp中,我有3个线程,其中tomcat无法在重新加载时阻止其中2个线程。
严重:Web应用程序[/ myapp]似乎已启动名为[Thread-8]的线程,但未能停止它。 这很可能造成内存泄漏。 mai 08,2013 11:22:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
这会导致每次重新加载时CPU使用率都会上升。
这是tomcat无法停止的线程之一:
在我的ServletContextListener中实现的一些代码:
public void contextInitialized(ServletContextEvent event)
{
final UpdaterThread updaterThread = new UpdaterThread();
updaterThread.start();
event.getServletContext().setAttribute("updaterthread", updaterThread);
}
public void contextDestroyed(ServletContextEvent event)
{
UpdaterThread updaterThread = (UpdaterThread) event.getServletContext().getAttribute("updaterthread");
if (updaterThread != null)
{
updaterThread.stopUpdater();
updaterThread.interrupt();
updaterThread = null;
}
}
还有UpdaterThread的重要部分:
public class UpdaterThread extends Thread implements Runnable
{
private boolean alive = true;
@Override
public void run()
{
while(true)
{
try
{
while (alive)
{
doUpdate();
sleep(60*1000);
}
}
catch (InterruptedException ie) {}
catch (Exception e) {}
}
}
public void stopUpdater()
{
alive = false;
}
}
有谁知道为什么这个线程不会停止? 有没有更好的方法来实现在特定时间做一些工作的线程?
据我所知,您实际上并没有停止线程。 您有两个while
循环,并且仅当您设置alive = false
时才停止内部。 外部将永远运行,什么也不做。 您也不会处理发送interrupt
,因此也不会终止线程。
我会做这样的事情:
public void run()
{
while(alive)
{
try
{
doUpdate();
sleep(60*1000);
}
catch (InterruptedException ie) {
alive = false;
}
}
}
另外,如果在创建线程时给它一个适当的名称,您将看到实际上是该线程引起了Tomcat报告的问题。
它与tomcat的ThreadLocal问题有关,请查看此文档http://wiki.apache.org/tomcat/MemoryLeakProtection
2010年3月16日,下午11:47:24 org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap严重:一个Web应用程序创建了一个ThreadLocal,其键值为[test.MyThreadLocal]类型(值[test.MyThreadLocal@4dbb9a58])和一个值类型[test.MyCounter](值[test.MyCounter@57922f46]),但在停止Web应用程序时无法将其删除。 为了防止内存泄漏,已将ThreadLocal强制删除。
http://forum.springsource.org/showthread.php?84202-Installation-ThreadLocal-forcefully-removed
对您的代码进行少量更改即可解决此问题
public class UpdaterThread extends Thread implements Runnable
{
private boolean alive = true;
@Override
public void run()
{
while(alive)
{
try
{
doUpdate();
sleep(60*1000);
}
catch (InterruptedException ie) {
//sleep interrupted
}
catch (Exception e) {
// exception in doUpdate method ? must handle this
}
}
}
public void stopUpdater()
{
alive = false;
}
}
但是,在while循环中Sleep
可能会导致性能问题。 仅当您想要暂停线程一段时间时才可以使用Thread.sleep
。 如果要等待某种情况,请勿使用它。
检查此SO问题: 线程睡眠称为循环
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.