I have some (Linux) C code which I am converting to Java. The code has a main loop that checks for a TERM signal from the OS at each looptop and blocks signals otherwise. This is so each "unit of work" it does in the loop is done completely (not interrupted by the TERM signal in the middle).
This has proved somewhat "interesting" to implement in Java. I have come up with some test code (below), which seems to work, but I am unsure if it will always work, or if I've just been "lucky" in my testing.
So, that's my question: is this good code or just code that happens to work sometimes?
TL;DR: work thread and shutdown thread call a common synchronized method
public class TestShutdownHook {
static int a = 0; /* should end up 0 */
static volatile int b = 0; /* exit together */
static boolean go = true; /* signaled to stop */
/*
* this simulates a process that we want to do completely
* or not at all.
*/
private static void doitall () {
System.out.println("start");
++a; /* simulates half the unit of work */
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("exception"); /* doesn't seem to happen */
}
System.out.println("end");
--a; /* the other half */
}
/*
* there can be only one
*/
private static synchronized void syncit (String msg) {
if (msg.equals("exit")) go = false;
if (go) doitall();
}
/*
* starts a thread to wait for a shutdown signal,
* then goes into the 'while go doit' loop
*/
public static void main(String[] args) throws InterruptedException {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
int n = 0;
System.out.println("Shutdown coming...");
syncit("exit"); /* can't happen while main is in syncit? */
System.out.println("Shutdown hook! " + a);
/* this isn't really needed, just lets us see "goodbye" */
while (b == 0) ++n;
System.out.println("adios..."+n);
}
});
while (go) {
syncit("loop");
// there needs to be something else in this loop
// otherwise, we will starve the shutdown thread.
// either of the two lines below seem sufficient
System.out.println("ok");
Thread.sleep(1);
}
System.out.println("goodbye");
b = 1;
}
}