簡體   English   中英

Tomcat無法停止webapp中的線程

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM