Search code examples
javadaemon

How do I create a daemon which executes TimerTasks?


I need to create a daemon in Java which periodically retrieves data via HTTP and stores that in a database.

When the main thread starts up, it reads the data sources and poll intervals from a configuration file and creates a TimerTask with the appropriate interval for each data source. In addition, it calls Runtime.getRuntime().addShutdownHook() to add a shutdown hook which performs any cleanup needed before shutdown. After that, the main thread has nothing else to do.

The daemon is intended for use in a classic Unix environment, i.e. controlled with a start/stop script, though it should be portable to other OSes (say, Windows with SrvAny).

How would I go about this? If I just let the main thread exit, will the TimerTask instances keep the VM running until all of them have been cancelled? If not, how would I accomplish this?


Solution

  • It depends on the Timer on which the TimerTask was scheduled: if that Timer was created not to run its tasks as daemons, a pending TimerTask will keep the VM alive even after the main thread has finished its work. This is the case for all Timer constructors which do not take a boolean argument, or where the boolean argument is false.

    The following seems to work as intended:

    package com.example.daemon;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class SampleDaemon {
        private static Timer testTimer = new Timer(false);
    
        public static void main(String[] args) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    System.out.println("Received shutdown request!");
                    if (testTimer != null)
                        testTimer.cancel();
                    testTimer = null;
                }
            });
            testTimer.schedule(new TestTimerTask(), new Date(), 2000);
        }
    
        private static class TestTimerTask extends TimerTask {
            @Override
            public void run() {
                System.out.println("Still running…");
            }
        }
    }
    

    It prints Still running… every 2 seconds. When the JVM receives a SIGTERM, the program prints Received shutdown request! and exits. This can also be accomplished by sending Ctrl+C from the console. SIGHUP does the same as SIGTERM.

    SIGCONT has no effect; SIGUSR1 results in a hard exit (presumably the same as SIGKILL), i.e. without executing the shutdown hook.