Tomcat не может остановить поток в веб-приложении

В моем веб-приложении у меня есть 3 потока, в которых tomcat не может остановить 2 из них при перезагрузке.

SEVERE: веб-приложение [/myapp], похоже, запустило поток с именем [Thread-8], но не смогло его остановить. Это очень вероятно, чтобы создать утечку памяти. май 08, 2013 11:22:40 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

Это приводит к увеличению загрузки процессора при каждой перезагрузке.

Вот один из потоков, который 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 ответа

Решение

Насколько я вижу, вы на самом деле не останавливаете свою нить вообще. У вас есть два while петли, и вы останавливаете только внутренний, когда вы установите alive = false, Внешнее будет работать вечно, ничего не делая. Вы также не справляетесь с interrupt ваша отправка, так что это не приведет к прекращению потока.

Я бы вместо этого сделал что-то вроде этого:

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

Кроме того, если вы дадите своему потоку правильное имя при создании, вы увидите, действительно ли этот поток вызывает проблему, о которой сообщает Tomcat.

это связано с проблемами ThreadLocal с tomcat, проверьте этот документ http://wiki.apache.org/tomcat/MemoryLeakProtection

16 марта 2010 г. 11:47:24 org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap SEVERE: веб-приложение создало ThreadLocal с ключом типа [test.MyThreadLocal] (значение [test.MyThreadLocal@4dbb9a58]) и значением типа [test.MyCounter] (значение [test.MyCounter@57922f46]), но не удалось удалить его при остановке веб-приложения. Чтобы предотвратить утечку памяти, 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;
 }
}

Тем не мение, Sleep в цикле while может возникнуть проблема с производительностью. Вы могли бы использовать Thread.sleep только если вы хотите приостановить вашу ветку на некоторое время. Не используйте его, если хотите дождаться какого-то состояния.

Проверьте этот вопрос SO: Thread-sleep-call-in-loop

Другие вопросы по тегам