user149408
user149408

Reputation: 5881

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?

Upvotes: 1

Views: 243

Answers (2)

user149408
user149408

Reputation: 5881

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.

Upvotes: 1

Joni
Joni

Reputation: 111239

Threads in Java have a flag to indicate if they should keep the jvm alive or not. This flag is called "daemon": the jvm will exit when only daemon threads are running.

The thread started by Timer is not a daemon thread by default, so it will keep the jvm alive, which is what you want. If you wanted the jvm to exit, you could create the timer with new Timer(true) - this would set the daemon flag. https://docs.oracle.com/javase/10/docs/api/java/util/Timer.html#%3Cinit%3E(boolean)

Upvotes: 1

Related Questions