Tomcat无法在webapp中停止线程

时间:2013-05-08 10:29:37

标签: java multithreading servlets

在我的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;
    }
}

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

3 个答案:

答案 0 :(得分:5)

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

我会做这样的事情:

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

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

答案 1 :(得分:1)

它与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])但无法在网络上删除它   申请被停止了。为了防止内存泄漏,ThreadLocal有   被强行拆除。

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

答案 2 :(得分: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;
 }
}

但是,while循环中的Sleep可能会产生性能问题。仅当您想要暂停线程一段时间时,才可以使用Thread.sleep。如果你想等待一些条件,请不要使用它。

检查此问题: Thread-sleep-called-in-loop