You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by "Terence M. Bandoian" <te...@tmbsw.com> on 2011/07/12 03:06:37 UTC

Terminating Timer Thread Gracefully

  Hi-

I've been testing a web application on:

Tomcat 6.0.32 (32-bit)
Sun/Oracle JRE 1.6.0_25 (32-bit)
Windows Server 2008 R2

The web application includes a ServletContextListener which creates a 
Timer in the contextInitialized method to perform periodic maintenance.  
To no avail, I spent quite a bit of time trying to eliminate the "The 
web application appears to have started a thread..." error message from 
the logs including logging the cancellation of the timer in the 
contextDestroyed method of the ServletContextListener.  Finally, in 
contextDestroyed, I inserted a call to Thread.sleep after canceling the 
timer and the error message disappeared.

Is there some other way to eliminate this message that I've missed?

-Terence Bandoian


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  On 1:59 PM, Bill Miller wrote:
> The problem is obviously that the thread within the Timer needs time to properly shutdown, the
> non-obvious part is "how long does it need, and how do you detect it's done?". Normally you would do
> a Thread.join() to ensure a thread has stopped before continuing, but as you mentioned before you
> don't have access to the true thread instance in this case.

That's how it looks to me.  Time and possibly a context switch.

> I'd say that the Thread.sleep() is doing the same as a Thread.join() would in this case, the only
> problem I see is that if your application is intended to run on different hardware the hardcoded
> 1000ms delay may not be long enough in some situations. :(

Right.

> Have you checked to see if there are any methods available to indicate if the timer has completed
> its shutdown? (My memory is unclear about this and the JavaDoc isn't handy either... maybe there's
> another object you need to instantiate to control Timer objects??)

Nothing in Timer.  Seems like I could potentially create a Thread and 
roll my own timing mechanism and then interrupt and join the Thread in 
contextDestroyed but that may be more complexity than is warranted.  
Might be fun though.

> Bill

Thanks.

-Terence


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Terminating Timer Thread Gracefully

Posted by Bill Miller <mi...@gmail.com>.
The problem is obviously that the thread within the Timer needs time to properly shutdown, the
non-obvious part is "how long does it need, and how do you detect it's done?". Normally you would do
a Thread.join() to ensure a thread has stopped before continuing, but as you mentioned before you
don't have access to the true thread instance in this case. 

I'd say that the Thread.sleep() is doing the same as a Thread.join() would in this case, the only
problem I see is that if your application is intended to run on different hardware the hardcoded
1000ms delay may not be long enough in some situations. :(

Have you checked to see if there are any methods available to indicate if the timer has completed
its shutdown? (My memory is unclear about this and the JavaDoc isn't handy either... maybe there's
another object you need to instantiate to control Timer objects??)

Bill
-----Original Message-----
From: Terence M. Bandoian [mailto:terence@tmbsw.com] 
Sent: July 12, 2011 3:47 PM
To: Tomcat Users List
Subject: Re: Terminating Timer Thread Gracefully

  Hi, Kris-

I tried using ScheduledExecutorService but ran into the same problem.  
After awaiting termination:

             executorService.shutdown();

             try
             {
                 while ( !executorService.awaitTermination(
                     1, TimeUnit.SECONDS ) );

                 Thread.sleep( 1000 );
             }
             catch ( InterruptedException ie )
             {
             }

I still had to insert a call to Thread.sleep to prevent the error 
message from being written to the logs.

Thanks.

-Terence Bandoian

On 1:59 PM, Kris Schneider wrote:
> On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
> <Ch...@unisys.com>  wrote:
>>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>>> Subject: Terminating Timer Thread Gracefully
>>> Finally, in contextDestroyed, I inserted a call to
>>> Thread.sleep after canceling the timer and the error
>>> message disappeared.
>> You should be able to do a Thread.join() using the timer's Thread object rather than sleeping.
> But Timer doesn't expose its thread. An alternative would be use
> something like Executors.newSingleThreadScheduledExecutor() to get a
> ScheduledExecutorService. The executor can be used to schedule a
> Runnable with a fixed rate or delay. When the context is destroyed,
> shutdown the executor and await its termination.
>
>>   - Chuck

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  On 1:59 PM, Pid wrote:
> On 14/07/2011 06:05, Terence M. Bandoian wrote:
>>   On 1:59 PM, Pid wrote:
>>> ATimerTask is a private instance in AServletContextListener, is this
>>> necessary and if so, why?
>>>
>>> What logic is contained in ATimerTask?
>>>
>>> Are you overriding TimerTask.cancel() and do you catch
>>> InterruptedException?
>>>
>>>
>>> p
>> Hi, Pid-
>>
>> For the sake of clarity, I'll repeat this here:
>>
>> public class AServletContextListener implements ServletContextListener
>> {
>>      private Timer timer;
>>      private ATimerTask timerTask;
> Yes, but why is the timerTask an instance field?  Put another way, why
> is there a reference to it outside of the contextInitialized() method?
>
>
>>      public void contextInitialized( ServletContextEvent sce )
>>      {
>>          if ( timer == null )
>>          {
>>              Calendar firstRunTime;
>>
>>              timer = new Timer( true );
>>              timerTask = new ATimerTask();
>>
>>              firstRunTime = new GregorianCalendar();
>>              firstRunTime.set( Calendar.HOUR_OF_DAY, 12 );
>>              firstRunTime.set( Calendar.MINUTE, 0 );
>>              firstRunTime.set( Calendar.SECOND, 0 );
>>              firstRunTime.set( Calendar.MILLISECOND, 0 );
>>
>>              timer.scheduleAtFixedRate(
>>                  timerTask, firstRunTime.getTime(), 1000 * 60 * 60 * 24 );
>>          }
>>      }
>>
>>      public void contextDestroyed( ServletContextEvent sce )
>>      {
>>          if ( timer != null )
>>          {
>>              timer.cancel();
>>              timer.purge();
>>
>>              timer = null;
>>              timerTask = null;
>>
>>              try
>>              {
>>                  Thread.sleep( 1000 );
>>              }
>>              catch ( InterruptedException ie )
>>              {
>>              }
>>          }
>>      }
>> }
>>
>> It isn't absolutely necessary but why would I make the ATimerTask
>> reference anything but private?
> As above.
>
> The only reason to keep a handle on the task itself is if you're calling
> cancel on the task - but you aren't doing that.  Maybe you should?
>


You're right, there's no reason for the ATimerTask reference to be a 
instance variable.  I did try canceling the tasks individually before 
canceling and purging the timer but it made no difference.


>> The timer tasks in the application perform some very straightforward
>> database and file system maintenance when their run methods are invoked
>> that might take up to half a second each.  None override the cancel
>> method.  All are scheduled to execute on a daily or weekly basis and
>> none at even close to the same time of day.
> The timer.cancel() method doesn't interrupt or stop a running task
> immediately, it just prevents it from running again.
>
> Your timer creates as daemon threads - perhaps you could assign a name
> too, and then report (just for confirmation) that it is the expected
> thread name(s) Tomcat's complaining is still running?
>
>
>> Also, while testing for ways to prevent the error message from being
>> written to the logs, I commented out the run method bodies of the timer
>> tasks so that they returned immediately and, given that I know the
>> schedule, none of the timer tasks were executing when I stopped or
>> restarted Tomcat.
> That reads (to me) like you're saying that if you comment out the run
> methods, everything is OK.  Is this correct?


When I comment out the run method bodies, I still get the error message 
in the logs unless I insert the call to Thread.sleep.

Thanks again.

-Terence


>
> p
>
>> The InterruptedException is caught and logged if it occurs.  I've never
>> seen it in the logs.
>>
>> Thanks.
>>
>> -Terence


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Pid <pi...@pidster.com>.
On 14/07/2011 06:05, Terence M. Bandoian wrote:
>  On 1:59 PM, Pid wrote:
>>
>> ATimerTask is a private instance in AServletContextListener, is this
>> necessary and if so, why?
>>
>> What logic is contained in ATimerTask?
>>
>> Are you overriding TimerTask.cancel() and do you catch
>> InterruptedException?
>>
>>
>> p
> 
> Hi, Pid-
> 
> For the sake of clarity, I'll repeat this here:
> 
> public class AServletContextListener implements ServletContextListener
> {
>     private Timer timer;
>     private ATimerTask timerTask;

Yes, but why is the timerTask an instance field?  Put another way, why
is there a reference to it outside of the contextInitialized() method?


>     public void contextInitialized( ServletContextEvent sce )
>     {
>         if ( timer == null )
>         {
>             Calendar firstRunTime;
> 
>             timer = new Timer( true );
>             timerTask = new ATimerTask();
> 
>             firstRunTime = new GregorianCalendar();
>             firstRunTime.set( Calendar.HOUR_OF_DAY, 12 );
>             firstRunTime.set( Calendar.MINUTE, 0 );
>             firstRunTime.set( Calendar.SECOND, 0 );
>             firstRunTime.set( Calendar.MILLISECOND, 0 );
> 
>             timer.scheduleAtFixedRate(
>                 timerTask, firstRunTime.getTime(), 1000 * 60 * 60 * 24 );
>         }
>     }
> 
>     public void contextDestroyed( ServletContextEvent sce )
>     {
>         if ( timer != null )
>         {
>             timer.cancel();
>             timer.purge();
> 
>             timer = null;
>             timerTask = null;
> 
>             try
>             {
>                 Thread.sleep( 1000 );
>             }
>             catch ( InterruptedException ie )
>             {
>             }
>         }
>     }
> }
> 
> It isn't absolutely necessary but why would I make the ATimerTask
> reference anything but private?

As above.

The only reason to keep a handle on the task itself is if you're calling
cancel on the task - but you aren't doing that.  Maybe you should?


> The timer tasks in the application perform some very straightforward
> database and file system maintenance when their run methods are invoked
> that might take up to half a second each.  None override the cancel
> method.  All are scheduled to execute on a daily or weekly basis and
> none at even close to the same time of day.

The timer.cancel() method doesn't interrupt or stop a running task
immediately, it just prevents it from running again.

Your timer creates as daemon threads - perhaps you could assign a name
too, and then report (just for confirmation) that it is the expected
thread name(s) Tomcat's complaining is still running?


> Also, while testing for ways to prevent the error message from being
> written to the logs, I commented out the run method bodies of the timer
> tasks so that they returned immediately and, given that I know the
> schedule, none of the timer tasks were executing when I stopped or
> restarted Tomcat.

That reads (to me) like you're saying that if you comment out the run
methods, everything is OK.  Is this correct?


p

> The InterruptedException is caught and logged if it occurs.  I've never
> seen it in the logs.
> 
> Thanks.
> 
> -Terence
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 



Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  On 1:59 PM, Pid wrote:
>
> ATimerTask is a private instance in AServletContextListener, is this
> necessary and if so, why?
>
> What logic is contained in ATimerTask?
>
> Are you overriding TimerTask.cancel() and do you catch InterruptedException?
>
>
> p

Hi, Pid-

For the sake of clarity, I'll repeat this here:

public class AServletContextListener implements ServletContextListener
{
     private Timer timer;
     private ATimerTask timerTask;

     public AServletContextListener()
     {
     }

     public void contextInitialized( ServletContextEvent sce )
     {
         if ( timer == null )
         {
             Calendar firstRunTime;

             timer = new Timer( true );
             timerTask = new ATimerTask();

             firstRunTime = new GregorianCalendar();
             firstRunTime.set( Calendar.HOUR_OF_DAY, 12 );
             firstRunTime.set( Calendar.MINUTE, 0 );
             firstRunTime.set( Calendar.SECOND, 0 );
             firstRunTime.set( Calendar.MILLISECOND, 0 );

             timer.scheduleAtFixedRate(
                 timerTask, firstRunTime.getTime(), 1000 * 60 * 60 * 24 );
         }
     }

     public void contextDestroyed( ServletContextEvent sce )
     {
         if ( timer != null )
         {
             timer.cancel();
             timer.purge();

             timer = null;
             timerTask = null;

             try
             {
                 Thread.sleep( 1000 );
             }
             catch ( InterruptedException ie )
             {
             }
         }
     }
}

It isn't absolutely necessary but why would I make the ATimerTask 
reference anything but private?

The timer tasks in the application perform some very straightforward 
database and file system maintenance when their run methods are invoked 
that might take up to half a second each.  None override the cancel 
method.  All are scheduled to execute on a daily or weekly basis and 
none at even close to the same time of day.

Also, while testing for ways to prevent the error message from being 
written to the logs, I commented out the run method bodies of the timer 
tasks so that they returned immediately and, given that I know the 
schedule, none of the timer tasks were executing when I stopped or 
restarted Tomcat.

The InterruptedException is caught and logged if it occurs.  I've never 
seen it in the logs.

Thanks.

-Terence


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Pid <pi...@pidster.com>.
On 12/07/2011 20:47, Terence M. Bandoian wrote:
>  Hi, Kris-
> 
> I tried using ScheduledExecutorService but ran into the same problem. 
> After awaiting termination:
> 
>             executorService.shutdown();
> 
>             try
>             {
>                 while ( !executorService.awaitTermination(
>                     1, TimeUnit.SECONDS ) );
> 
>                 Thread.sleep( 1000 );
>             }
>             catch ( InterruptedException ie )
>             {
>             }
> 
> I still had to insert a call to Thread.sleep to prevent the error
> message from being written to the logs.

ATimerTask is a private instance in AServletContextListener, is this
necessary and if so, why?

What logic is contained in ATimerTask?

Are you overriding TimerTask.cancel() and do you catch InterruptedException?


p

> 
> Thanks.
> 
> -Terence Bandoian
> 
> On 1:59 PM, Kris Schneider wrote:
>> On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
>> <Ch...@unisys.com>  wrote:
>>>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>>>> Subject: Terminating Timer Thread Gracefully
>>>> Finally, in contextDestroyed, I inserted a call to
>>>> Thread.sleep after canceling the timer and the error
>>>> message disappeared.
>>> You should be able to do a Thread.join() using the timer's Thread
>>> object rather than sleeping.
>> But Timer doesn't expose its thread. An alternative would be use
>> something like Executors.newSingleThreadScheduledExecutor() to get a
>> ScheduledExecutorService. The executor can be used to schedule a
>> Runnable with a fixed rate or delay. When the context is destroyed,
>> shutdown the executor and await its termination.
>>
>>>   - Chuck
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 



Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  For anyone who might be interested, this is what I ended up with for a 
scheduler:

public class AServletContextListener implements ServletContextListener
{

     private ScheduledExecutorService executor;


     /**
      * Constructs AServletContextListener object.
      */

     public AServletContextListener()
     {
     }


     /**
      * Invoked when context is initialized.
      *
      * @param    sce        triggering ServletContextEvent
      */

     public void contextInitialized( ServletContextEvent sce )
     {
         if ( executor == null )
         {
             executor = Executors.newSingleThreadScheduledExecutor();

             Calendar firstRunTime = new GregorianCalendar();
             firstRunTime.set( Calendar.HOUR_OF_DAY, 12 );
             firstRunTime.set( Calendar.MINUTE, 0 );
             firstRunTime.set( Calendar.SECOND, 0 );
             firstRunTime.set( Calendar.MILLISECOND, 0 );

             executor.scheduleAtFixedRate(
                 new ARunnable(),
                 firstRunTime.getTimeInMillis() - 
System.currentTimeMillis(),
                 1000 * 60 * 60 * 24,
                 TimeUnit.MILLISECONDS );
         }
     }


     /**
      * Invoked when context is destroyed.
      *
      * @param    sce        triggering ServletContextEvent
      */

     public void contextDestroyed( ServletContextEvent sce )
     {
         if ( executor != null )
         {
             boolean isTerminated = false;

             executor.shutdown();

             do
             {
                 try
                 {
                     isTerminated = executor.awaitTermination(
                         1, TimeUnit.SECONDS );
                 }
                 catch ( InterruptedException ignore )
                 {
                 }
             }
             while ( !isTerminated );

             executor = null;

             Thread.yield();
         }
     }

}

Thanks for all the suggestions and pointers.

-Terence


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  On 1:59 PM, Mark Thomas wrote:
> On 14/07/2011 23:59, Terence M. Bandoian wrote:
>>   On 1:59 PM, Mark Thomas wrote:
>>> On 14/07/2011 06:11, Terence M. Bandoian wrote:
>>>> I can live with this.  It's just one of those "it would be nice not to
>>>> have to explain" things and if Thread.sleep does the trick, I'm happy.
>>>> As I mentioned in my original post, I wanted to find out if there was a
>>>> another way to accomplish the same thing that I'd missed.
>>> Daft question, why not set clearReferencesStopTimerThreads="true" on the
>>> Context and get Tomcat to do the clean-up for you?
>>>
>>> Mark
>> With that set, I get a similar SEVERE error message that says the web
>> application has started but "failed to stop" a TimerThread and that it
>> was "forcibly canceled" to "prevent a memory leak".
> So what is to prevent you from using the same code Tomcat does to stop
> the thread properly?
>
> Mark

Yielding after canceling the timer appears to accomplish the same 
purpose.  Thanks for the pointer.

-Terence


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Mark Thomas <ma...@apache.org>.
On 14/07/2011 23:59, Terence M. Bandoian wrote:
>  On 1:59 PM, Mark Thomas wrote:
>> On 14/07/2011 06:11, Terence M. Bandoian wrote:
>>> I can live with this.  It's just one of those "it would be nice not to
>>> have to explain" things and if Thread.sleep does the trick, I'm happy.
>>> As I mentioned in my original post, I wanted to find out if there was a
>>> another way to accomplish the same thing that I'd missed.
>> Daft question, why not set clearReferencesStopTimerThreads="true" on the
>> Context and get Tomcat to do the clean-up for you?
>>
>> Mark
> 
> With that set, I get a similar SEVERE error message that says the web
> application has started but "failed to stop" a TimerThread and that it
> was "forcibly canceled" to "prevent a memory leak".

So what is to prevent you from using the same code Tomcat does to stop
the thread properly?

Mark



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  On 1:59 PM, Mark Thomas wrote:
> On 14/07/2011 06:11, Terence M. Bandoian wrote:
>> I can live with this.  It's just one of those "it would be nice not to
>> have to explain" things and if Thread.sleep does the trick, I'm happy.
>> As I mentioned in my original post, I wanted to find out if there was a
>> another way to accomplish the same thing that I'd missed.
> Daft question, why not set clearReferencesStopTimerThreads="true" on the
> Context and get Tomcat to do the clean-up for you?
>
> Mark

With that set, I get a similar SEVERE error message that says the web 
application has started but "failed to stop" a TimerThread and that it 
was "forcibly canceled" to "prevent a memory leak".

Thanks.

-Terence


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Mark Thomas <ma...@apache.org>.
On 14/07/2011 06:11, Terence M. Bandoian wrote:
> I can live with this.  It's just one of those "it would be nice not to
> have to explain" things and if Thread.sleep does the trick, I'm happy.
> As I mentioned in my original post, I wanted to find out if there was a
> another way to accomplish the same thing that I'd missed.

Daft question, why not set clearReferencesStopTimerThreads="true" on the
Context and get Tomcat to do the clean-up for you?

Mark



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  On 1:59 PM, Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Terence,
>
> On 7/12/2011 3:47 PM, Terence M. Bandoian wrote:
>> executorService.shutdown();
>>
>> try { while ( !executorService.awaitTermination( 1, TimeUnit.SECONDS
>> ) );
>>
>> Thread.sleep( 1000 ); } catch ( InterruptedException ie ) { }
>
> We use a ThreadPoolExecutor (which is an ExecutorService) in one of our
> projects, and we do something like the following:
>
>              int counter = 0; // Only emit messages every 10 seconds
>              while(true)
>              {
>                  if(_executor.isTerminated())
>                  {
>                      break;
>                  }
>                  else
>                  {
>                      if(++counter>  9)
>                      {
>                          if(!_executor.isTerminated())
>                          {
>                              logger.info("Still waiting on "
>                                          + (_executor.getQueue()
>                                             .size() + 1)
>                                          + " jobs to complete");
>                          }
>
>                          counter = 0;
>                      }
>
>                      // Sleep
>                      try { Thread.sleep(1000); }
>                      catch (InterruptedException ie) { /* do nothing */ }
>                  }
>              }
>
> This will test for completion every second, but only print warning
> messages every 10 seconds that the service is waiting for the jobs to
> complete.
>
> I suppose we could even do _executor.awaitTermination(1, SECOND) to
> jump-out a little early, but the point is that we loop waiting and also
> print job counts, too. That may help you observe what is going on.
>
> We don't run this in a webapp context, so we aren't ever having Tomcat
> try to detect these threads or anything.
>
> It's certainly possible that you are on the unfortunate end of a race
> condition where Tomcat starts it's loose-thread detection before the job
> thread has fully terminated and so the warning is spurious. Note that
> awaitTermination() and isTerminated() methods are only documented to
> return true when all jobs have completed and mention nothing about
> destruction of the actual threads that perform the jobs.


I thought this might be the case but wanted to check with the folks who 
know Tomcat much better than I do.  Apparently, the call to Thread.sleep 
provides the opportunity to destroy the Timer or 
ScheduledExecutorService thread before Tomcat makes its check.


> You may be out of luck from an API perspective, so perhaps an arbitrary
> Thread.sleep() may be your only option, here. You could, of course, tell
> Tomcat not to check for this kind of thing and the message(s) will go
> away. I think it's better to allow Tomcat to complain, but know that a
> message about a particular thread (you can name your threads by
> specifying a ThreadFactory) is spurious and that others should be
> investigated.
>


I can live with this.  It's just one of those "it would be nice not to 
have to explain" things and if Thread.sleep does the trick, I'm happy. 
As I mentioned in my original post, I wanted to find out if there was a 
another way to accomplish the same thing that I'd missed.


> I wonder if anyone would be interested in a regular expression for
> thread names that could be used to ignore certain threads during this
> loose-thread checking for cases like this.
>
> - -chris


Thanks.

-Terence

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Terence,

On 7/12/2011 3:47 PM, Terence M. Bandoian wrote:
> executorService.shutdown();
> 
> try { while ( !executorService.awaitTermination( 1, TimeUnit.SECONDS
> ) );
> 
> Thread.sleep( 1000 ); } catch ( InterruptedException ie ) { }


We use a ThreadPoolExecutor (which is an ExecutorService) in one of our
projects, and we do something like the following:

            int counter = 0; // Only emit messages every 10 seconds
            while(true)
            {
                if(_executor.isTerminated())
                {
                    break;
                }
                else
                {
                    if(++counter > 9)
                    {
                        if(!_executor.isTerminated())
                        {
                            logger.info("Still waiting on "
                                        + (_executor.getQueue()
                                           .size() + 1)
                                        + " jobs to complete");
                        }

                        counter = 0;
                    }

                    // Sleep
                    try { Thread.sleep(1000); }
                    catch (InterruptedException ie) { /* do nothing */ }
                }
            }

This will test for completion every second, but only print warning
messages every 10 seconds that the service is waiting for the jobs to
complete.

I suppose we could even do _executor.awaitTermination(1, SECOND) to
jump-out a little early, but the point is that we loop waiting and also
print job counts, too. That may help you observe what is going on.

We don't run this in a webapp context, so we aren't ever having Tomcat
try to detect these threads or anything.

It's certainly possible that you are on the unfortunate end of a race
condition where Tomcat starts it's loose-thread detection before the job
thread has fully terminated and so the warning is spurious. Note that
awaitTermination() and isTerminated() methods are only documented to
return true when all jobs have completed and mention nothing about
destruction of the actual threads that perform the jobs.

You may be out of luck from an API perspective, so perhaps an arbitrary
Thread.sleep() may be your only option, here. You could, of course, tell
Tomcat not to check for this kind of thing and the message(s) will go
away. I think it's better to allow Tomcat to complain, but know that a
message about a particular thread (you can name your threads by
specifying a ThreadFactory) is spurious and that others should be
investigated.

I wonder if anyone would be interested in a regular expression for
thread names that could be used to ignore certain threads during this
loose-thread checking for cases like this.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk4dyS0ACgkQ9CaO5/Lv0PAOpACfcPhCnHGhhC03dGcxKw5udCQZ
1NkAoKZEvqwIIYh3/sNqmdAJP7O7hKor
=HKaB
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  Hi, Kris-

I tried using ScheduledExecutorService but ran into the same problem.  
After awaiting termination:

             executorService.shutdown();

             try
             {
                 while ( !executorService.awaitTermination(
                     1, TimeUnit.SECONDS ) );

                 Thread.sleep( 1000 );
             }
             catch ( InterruptedException ie )
             {
             }

I still had to insert a call to Thread.sleep to prevent the error 
message from being written to the logs.

Thanks.

-Terence Bandoian

On 1:59 PM, Kris Schneider wrote:
> On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
> <Ch...@unisys.com>  wrote:
>>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>>> Subject: Terminating Timer Thread Gracefully
>>> Finally, in contextDestroyed, I inserted a call to
>>> Thread.sleep after canceling the timer and the error
>>> message disappeared.
>> You should be able to do a Thread.join() using the timer's Thread object rather than sleeping.
> But Timer doesn't expose its thread. An alternative would be use
> something like Executors.newSingleThreadScheduledExecutor() to get a
> ScheduledExecutorService. The executor can be used to schedule a
> Runnable with a fixed rate or delay. When the context is destroyed,
> shutdown the executor and await its termination.
>
>>   - Chuck

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Len Popp <le...@gmail.com>.
On Tue, Jul 12, 2011 at 10:03, David kerber <dc...@verizon.net> wrote:

> On 7/12/2011 9:59 AM, Kris Schneider wrote:
>
>> On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
>> <Ch...@unisys.com>  wrote:
>>
>>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>>>> Subject: Terminating Timer Thread Gracefully
>>>>
>>>
>>>  Finally, in contextDestroyed, I inserted a call to
>>>> Thread.sleep after canceling the timer and the error
>>>> message disappeared.
>>>>
>>>
>>> You should be able to do a Thread.join() using the timer's Thread object
>>> rather than sleeping.
>>>
>>
>> But Timer doesn't expose its thread. An alternative would be use
>> something like Executors.**newSingleThreadScheduledExecut**or() to get a
>> ScheduledExecutorService. The executor can be used to schedule a
>> Runnable with a fixed rate or delay. When the context is destroyed,
>> shutdown the executor and await its termination.
>>
>
> No need even to do that; just .cancel() the timer.


Except that didn't work, according to Terence, until he added a sleep after
cancelling the timer. Could that be because the timer thread is busy
performing tasks that take some time to run? After cancel() is called the
timer thread "terminates gracefully" (according to the Java doc) which means
waiting for the currently executing task, if any, to finish.
-- 
Len

Re: Terminating Timer Thread Gracefully

Posted by Kris Schneider <ks...@gmail.com>.
On Tue, Jul 12, 2011 at 10:03 AM, David kerber <dc...@verizon.net> wrote:
> On 7/12/2011 9:59 AM, Kris Schneider wrote:
>>
>> On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
>> <Ch...@unisys.com>  wrote:
>>>>
>>>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>>>> Subject: Terminating Timer Thread Gracefully
>>>
>>>> Finally, in contextDestroyed, I inserted a call to
>>>> Thread.sleep after canceling the timer and the error
>>>> message disappeared.
>>>
>>> You should be able to do a Thread.join() using the timer's Thread object
>>> rather than sleeping.
>>
>> But Timer doesn't expose its thread. An alternative would be use
>> something like Executors.newSingleThreadScheduledExecutor() to get a
>> ScheduledExecutorService. The executor can be used to schedule a
>> Runnable with a fixed rate or delay. When the context is destroyed,
>> shutdown the executor and await its termination.
>
> No need even to do that; just .cancel() the timer.

Maybe. It sounds like that's been working for you, but I thought the
OP had already tried that. A potential issue with Timer.cancel() is
that there really aren't any guarantees about when the associated
thread is terminated and there certainly isn't any way for external
code to interact with it. Using something like an ExecutorService just
seems like a better approach to this sort of thing.

-- 
Kris Schneider

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by David kerber <dc...@verizon.net>.
On 7/12/2011 9:59 AM, Kris Schneider wrote:
> On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
> <Ch...@unisys.com>  wrote:
>>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>>> Subject: Terminating Timer Thread Gracefully
>>
>>> Finally, in contextDestroyed, I inserted a call to
>>> Thread.sleep after canceling the timer and the error
>>> message disappeared.
>>
>> You should be able to do a Thread.join() using the timer's Thread object rather than sleeping.
>
> But Timer doesn't expose its thread. An alternative would be use
> something like Executors.newSingleThreadScheduledExecutor() to get a
> ScheduledExecutorService. The executor can be used to schedule a
> Runnable with a fixed rate or delay. When the context is destroyed,
> shutdown the executor and await its termination.

No need even to do that; just .cancel() the timer.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Kris Schneider <ks...@gmail.com>.
On Tue, Jul 12, 2011 at 7:59 AM, Caldarale, Charles R
<Ch...@unisys.com> wrote:
>> From: Terence M. Bandoian [mailto:terence@tmbsw.com]
>> Subject: Terminating Timer Thread Gracefully
>
>> Finally, in contextDestroyed, I inserted a call to
>> Thread.sleep after canceling the timer and the error
>> message disappeared.
>
> You should be able to do a Thread.join() using the timer's Thread object rather than sleeping.

But Timer doesn't expose its thread. An alternative would be use
something like Executors.newSingleThreadScheduledExecutor() to get a
ScheduledExecutorService. The executor can be used to schedule a
Runnable with a fixed rate or delay. When the context is destroyed,
shutdown the executor and await its termination.

>  - Chuck

-- 
Kris Schneider

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Terminating Timer Thread Gracefully

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Terence M. Bandoian [mailto:terence@tmbsw.com] 
> Subject: Terminating Timer Thread Gracefully

> Finally, in contextDestroyed, I inserted a call to 
> Thread.sleep after canceling the timer and the error
> message disappeared.

You should be able to do a Thread.join() using the timer's Thread object rather than sleeping.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Terminating Timer Thread Gracefully

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
  Thanks to all who replied.

Functionally, the servlet context listener is implemented as follows:

public class AServletContextListener implements ServletContextListener
{
     private Timer timer;
     private ATimerTask timerTask;

     public AServletContextListener()
     {
     }

     public void contextInitialized( ServletContextEvent sce )
     {
         if ( timer == null )
         {
             Calendar firstRunTime;

             timer = new Timer( true );
             timerTask = new ATimerTask();

             firstRunTime = new GregorianCalendar();
             firstRunTime.set( Calendar.HOUR_OF_DAY, 12 );
             firstRunTime.set( Calendar.MINUTE, 0 );
             firstRunTime.set( Calendar.SECOND, 0 );
             firstRunTime.set( Calendar.MILLISECOND, 0 );

             timer.scheduleAtFixedRate(
                 timerTask, firstRunTime.getTime(), 1000 * 60 * 60 * 24 );
         }
     }

     public void contextDestroyed( ServletContextEvent sce )
     {
         if ( timer != null )
         {
             timer.cancel();
             timer.purge();

             timer = null;
             timerTask = null;

             try
             {
                 Thread.sleep( 1000 );
             }
             catch ( InterruptedException ie )
             {
             }
         }
     }
}

If I remove the call to Thread.sleep, the error message is written to 
the logs.

Timer tasks are scheduled no more often than daily and none are 
executing when the context is destroyed.  The one second delay appears 
to work reliably.  I haven't yet tested with other values.

The real question may be, as Len suggested, what does "terminates 
gracefully" mean in relation to the execution thread of a canceled Timer?

Thanks again.

-Terence Bandoian

On 1:59 PM, Pid wrote:
> On 12/07/2011 02:06, Terence M. Bandoian wrote:
>>   Hi-
>>
>> I've been testing a web application on:
>>
>> Tomcat 6.0.32 (32-bit)
>> Sun/Oracle JRE 1.6.0_25 (32-bit)
>> Windows Server 2008 R2
>>
>> The web application includes a ServletContextListener which creates a
>> Timer in the contextInitialized method to perform periodic maintenance.
>> To no avail, I spent quite a bit of time trying to eliminate the "The
>> web application appears to have started a thread..." error message from
>> the logs including logging the cancellation of the timer in the
>> contextDestroyed method of the ServletContextListener.  Finally, in
>> contextDestroyed, I inserted a call to Thread.sleep after canceling the
>> timer and the error message disappeared.
>>
>> Is there some other way to eliminate this message that I've missed?
> Hard to know, can you post the code you used to start/stop the timer?
>
>
> p
>
>
>> -Terence Bandoian
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by David kerber <dc...@verizon.net>.
On 7/12/2011 4:11 AM, Pid wrote:
> On 12/07/2011 02:06, Terence M. Bandoian wrote:
>>   Hi-
>>
>> I've been testing a web application on:
>>
>> Tomcat 6.0.32 (32-bit)
>> Sun/Oracle JRE 1.6.0_25 (32-bit)
>> Windows Server 2008 R2
>>
>> The web application includes a ServletContextListener which creates a
>> Timer in the contextInitialized method to perform periodic maintenance.
>> To no avail, I spent quite a bit of time trying to eliminate the "The
>> web application appears to have started a thread..." error message from
>> the logs including logging the cancellation of the timer in the
>> contextDestroyed method of the ServletContextListener.  Finally, in
>> contextDestroyed, I inserted a call to Thread.sleep after canceling the
>> timer and the error message disappeared.
>>
>> Is there some other way to eliminate this message that I've missed?

I believe contextDestroyed is the correct location, but I use 
timer.cancel() to shutdown the timer, rather than touching the thread 
itself, and it seems to work fine.

D

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Terminating Timer Thread Gracefully

Posted by Pid <pi...@pidster.com>.
On 12/07/2011 02:06, Terence M. Bandoian wrote:
>  Hi-
> 
> I've been testing a web application on:
> 
> Tomcat 6.0.32 (32-bit)
> Sun/Oracle JRE 1.6.0_25 (32-bit)
> Windows Server 2008 R2
> 
> The web application includes a ServletContextListener which creates a
> Timer in the contextInitialized method to perform periodic maintenance. 
> To no avail, I spent quite a bit of time trying to eliminate the "The
> web application appears to have started a thread..." error message from
> the logs including logging the cancellation of the timer in the
> contextDestroyed method of the ServletContextListener.  Finally, in
> contextDestroyed, I inserted a call to Thread.sleep after canceling the
> timer and the error message disappeared.
> 
> Is there some other way to eliminate this message that I've missed?

Hard to know, can you post the code you used to start/stop the timer?


p


> -Terence Bandoian
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>