[英]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.