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?
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.