【问题标题】:Tomcat fails to stop thread in webappTomcat 无法停止 webapp 中的线程
【发布时间】:2013-05-02 13:05:21
【问题描述】:

在我的 web 应用程序中,我有 3 个线程,其中 tomcat 在重新加载时无法停止其中的 2 个。

严重:Web 应用程序 [/myapp] 似乎已经启动了一个名为 [Thread-8] 的线程,但未能停止它。这很可能造成内存泄漏。 2013 年 5 月 8 日上午 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;
    }
}

有谁知道为什么这个线程不会停止?有没有更好的方法来实现一个线程在特定时间做一些工作?

【问题讨论】:

  • 为什么你同时拥有while(true)while(alive)?即使您将alive 设置为false,它也会无限循环。

标签: java multithreading servlets


【解决方案1】:

据我所知,您实际上根本没有停止线程。您有两个while 循环,并且只有在设置alive = false 时才停止内部循环。外部将永远运行,什么也不做。你也不处理interrupt你的发送,所以也不会终止线程。

我会改为这样做:

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

另外,如果你在创建线程时给它一个正确的名称,你会看到它是否真的是那个线程导致了 Tomcat 报告的问题。

【讨论】:

    【解决方案2】:

    与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])但在 web 时未能将其删除 应用程序已停止。为了防止内存泄漏,ThreadLocal 具有 被强行删除。

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

    【讨论】:

      【解决方案3】:

      对您的代码稍作改动以解决此问题

      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。如果您想等待某些条件,请不要使用它。

      检查这个 SO 问题: Thread-sleep-called-in-loop

      【讨论】:

        猜你喜欢
        • 2012-03-29
        • 2016-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-30
        • 2021-06-28
        • 1970-01-01
        相关资源
        最近更新 更多