在我的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;
}
}
有谁知道为什么这个帖子不会停止?有没有更好的方法来实现一个线程在特定时间做一些工作?
答案 0 :(得分:5)
据我所知,你实际上根本没有停止你的线程。您有两个while
循环,只有在设置alive = false
时才会停止内部循环。外在将永远运行,什么也不做。您也不处理发送的interrupt
,因此也不会终止该线程。
我会做这样的事情:
public void run()
{
while(alive)
{
try
{
doUpdate();
sleep(60*1000);
}
catch (InterruptedException ie) {
alive = false;
}
}
}
此外,如果在创建线程时给你的线程一个正确的名称,你会看到它是否真的是导致Tomcat报告问题的线程。
答案 1 :(得分:1)
它与tomcat的ThreadLocal问题有关,检查此文档 http://wiki.apache.org/tomcat/MemoryLeakProtection
2010年3月16日下午11:47:24 org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap SEVERE:Web应用程序创建了ThreadLocal 使用[test.MyThreadLocal]类型的键(值 [test.MyThreadLocal@4dbb9a58])和类型为[test.MyCounter]的值 (值[test.MyCounter@57922f46])但无法在网络上删除它 申请被停止了。为了防止内存泄漏,ThreadLocal有 被强行拆除。
http://forum.springsource.org/showthread.php?84202-Installation-ThreadLocal-forcefully-removed
答案 2 :(得分:0)
修复此问题的代码中的小变化
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
。如果你想等待一些条件,请不要使用它。
检查此问题: Thread-sleep-called-in-loop