Reputation: 439
In my webapp I have 3 threads where tomcat fails to stop 2 of these on reload.
SEVERE: The web application [/myapp] appears to have started a thread named [Thread-8] but has failed to stop it. This is very likely to create a memory leak. mai 08, 2013 11:22:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
This causes the CPU usage to rise for each reload.
Here is one of the threads that tomcat fails to stop:
Some of the code implemented in my 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;
}
}
And the important parts of 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;
}
}
Does anyone have any idea why this thread don't stops? Is there a better way to implement a thread doing some work at specific times?
Upvotes: 2
Views: 8547
Reputation: 11298
A Small change in your code to fix this issue
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;
}
}
However, Sleep
in while loop likely to create a performance issue. You could use Thread.sleep
only if you want to suspend your thread for some time. Do not use it if you want to wait for some condition.
Check this SO question : Thread-sleep-called-in-loop
Upvotes: 0
Reputation: 13821
As far as I can see, you're not actually stopping your thread at all. You have two while
loops, and you only stop the inner when you set alive = false
. The outer will run forever, doing nothing. You also don't handle the interrupt
your sending, so that won't terminate the thread either.
I would instead do something like this:
public void run()
{
while(alive)
{
try
{
doUpdate();
sleep(60*1000);
}
catch (InterruptedException ie) {
alive = false;
}
}
}
Also, if you give your thread a proper name when creating it, you'll see if it's actually that thread that is causing the problem Tomcat is reporting.
Upvotes: 4
Reputation: 7412
it’s related to ThreadLocal issues with tomcat, Check this document http://wiki.apache.org/tomcat/MemoryLeakProtection
Mar 16, 2010 11:47:24 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap SEVERE: A web application created a ThreadLocal with key of type [test.MyThreadLocal] (value [test.MyThreadLocal@4dbb9a58]) and a value of type [test.MyCounter] (value [test.MyCounter@57922f46]) but failed to remove it when the web application was stopped. To prevent a memory leak, the ThreadLocal has been forcibly removed.
http://forum.springsource.org/showthread.php?84202-Installation-ThreadLocal-forcefully-removed
Upvotes: 1