1

I want to run a method every 22 minutes on a servlet running on Tomcat. So I'm using this code:

Timer timer = new Timer();

timer.schedule(new TimerTask() {
    @Override
    public void run() {

        try {
            update();
        } catch (SQLException | NamingException | InterruptedException e1) {
            e1.printStackTrace();
        }
    }
}, 22 * 60 * 1000, 22 * 60 * 1000);

I've got a feeling this is a terrible way to do it as I'm getting errors all the time regarding timers, and whenever I uploaded a new version of the servlet I don't think it stops the previous timer. I then get database connection warnings. If I reset everything and start fresh its fine.

javax.naming.NameNotFoundException: Name comp is not bound in this Context
    at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
    at org.apache.naming.SelectorContext.lookup(SelectorContext.java:152)
    at javax.naming.InitialContext.lookup(InitialContext.java:411)
    at my.app.database.DatabaseManager.connect(DatabaseManager.java:44)
    at my.app.database.DatabaseManager.returnInfo(DatabaseManager.java:133)
    at my.app.genParse.Generate.updateHistory(Generate.java:89)
    at my.app.MyServer$1.run(MyServer.java:52)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)

And also on re-launch with the new version:

SEVERE: The web application [/myApp] appears to have started a thread named [Timer-7] but has failed to stop it. This is very likely to create a memory leak.

Whats a better way to achieve or avoid this?

RegDHunter
  • 385
  • 2
  • 5
  • 9

3 Answers3

1

An alternative to using timer tasks has been discussed here. Using the ScheduledThreadpoolExecutor class MAY help with the problem of having multiple threads still running when you upload a new version however I cannot say for sure that it will. This class is also preferred over the Timer class for various reasons discussed in the javadoc.

Community
  • 1
  • 1
nattyddubbs
  • 2,085
  • 15
  • 24
1

You shouldnt really use a Timer within a container - Timer spawn/reuse a thread thats managed outside of the container and this can cause problems.

Note too that as Timer uses a single thread if one instance of it takes too long the others accuracy can suffer.

Finally, if a Timer throws an unchecked exception the Timer thread is terminated.

For these (and other) reasons it has largely fallen out of favour - ScheduledThreadPoolExecutor is a better choice.

Again though, user managed threads within a container can be tricky. JSR-236 (Concurrency Utilities for the Java EE platform) will provide a mechanism to do so in the future, but for now its best avoided.

You can try schedule repeatable tasks via cron perhaps that could in turn call a dedicated servlet (or similar) on a regular basis

Sean Landsman
  • 7,033
  • 2
  • 29
  • 33
0

Use a ServletContextListener to start and stop your Timer when the web application starts and stops.

Mark Thomas
  • 16,339
  • 1
  • 39
  • 60