Reputation: 5881
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
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
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