繁体   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