2013-05-08 117 views
2

在我的web應用程序中,我有3個線程,其中tomcat未能在重新加載時停止其中的2個線程。Tomcat無法停止webapp中的線程

嚴重:Web應用程序[/ myapp]似乎已經啓動了一個名爲[Thread-8]的線程,但未能阻止它。這很可能造成內存泄漏。 脈08,2013上午11時22分40秒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; 
    } 
} 

有沒有人有任何想法,爲什麼這個線程不停止?有沒有更好的方法來實現在特定時間執行某項工作的線程?

+1

爲什麼你有兩個'而(真)'和'而(活着)'?即使你將'alive'設置爲false,它也會無休止地循環。 – NilsH 2013-05-08 10:32:01

回答

5

就我所見,你實際上並沒有停止你的線程。你有兩個while循環,當你設置alive = false時,你只能停止內部循環。外在將永遠運行,無所事事。你也不會處理你的發送,所以也不會終止線程。

我反而做這樣的事情:

public void run() 
{ 
    while(alive) 
    { 
     try 
     { 
      doUpdate(); 
      sleep(60*1000); 
     } 
     catch (InterruptedException ie) { 
      alive = false; 
     } 
    } 
} 

另外,如果你在創建時,它給你的線程一個合適的名字,你會看到,如果它實際上是線程引起Tomcat的報告問題。

+0

當然可以。謝謝。 – sjallamander 2013-05-08 11:01:52

1

它涉及與Tomcat的ThreadLocal的問題,檢查本文檔 http://wiki.apache.org/tomcat/MemoryLeakProtection

2010年3月16日下午11時47分24秒org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap嚴重:一個網頁應用程序創建了一個類型爲[test.MyThreadLocal](值爲 [[email protected]])並且類型爲[test.MyCounter] (值爲[[email protected]])的ThreadLocal的ThreadLocal ,但未能刪除它在網絡 應用程序停止時。爲防止內存泄漏,ThreadLocal已被強制刪除 。

http://forum.springsource.org/showthread.php?84202-Installation-ThreadLocal-forcefully-removed

+0

它沒有說OPs警告中的線程局部變量。 – NilsH 2013-05-08 10:46:26

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; 
} 
} 

然而,Sleep在while循環可能造成性能問題。僅當您想暫停線索一段時間時,纔可以使用Thread.sleep。如果您想等待某種情況,請勿使用它。

入住這太問題:Thread-sleep-called-in-loop