2013-05-08 67 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