I think the problem is that your shutdown hook is incomplete. The hook needs to wait until the "SAFELY SHUTTING DOWN" action is complete before it returns.
Here is a modified version of your code that does work.
public static void main(String... args) {
final AtomicBoolean shouldBeRunning = new AtomicBoolean(true);
final AtomicBoolean isRunning = new AtomicBoolean(false);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
shouldBeRunning.set(false);
System.out.println("shutdown hook activated");
while(isRunning.get()) {
try {
System.out.println("waiting on safe shutdown to complete");
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
new Thread(new Runnable() {
public void run() {
isRunning.set(true);
while (shouldBeRunning.get()) {
try {
System.out.println("sleeping for 1 seconds!");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("INTERRUPTED");
break;
}
}
System.out.println("SAFELY SHUTTING DOWN");
isRunning.set(false);
}
}).start();
}
public static void main(String... args) throws InterruptedException {
final AtomicBoolean shouldBeRunning = new AtomicBoolean(true);
final AtomicBoolean isRunning = new AtomicBoolean(false);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
shouldBeRunning.set(false);
System.out.println("shutdown hook activated");
while(isRunning.get()) {
try {
System.out.println("waiting on safe shutdown to complete");
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
new Thread(new Runnable() {
public void run() {
isRunning.set(true);
while (shouldBeRunning.get()) {
try {
System.out.println("sleeping for 1 second!");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("INTERRUPTED");
break;
}
}
System.out.println("SAFELY SHUTTING DOWN");
isRunning.set(false);
}
}).start();
}
The output is:
sleeping for 1 second!
sleeping for 1 second!
shutdown hook activated
waiting on safe shutdown to complete
waiting on safe shutdown to complete
SAFELY SHUTTING DOWN
Tracking all the non daemon threads and joining on them in the shutdown hook won't allow you to prevent your program from being terminated since the shutdown hook has a time limit. When this time expires the JVM will exit even if the hook has not completed.