我认为问题在于您的关闭挂钩不完整。钩子需要等到“安全关闭”操作完成后才返回。
这是您的代码的修改版本,它确实有效。
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();
}
输出是:
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
跟踪所有非守护线程并在关闭挂钩中加入它们不会让您阻止程序被终止,因为关闭挂钩有时间限制。当这个时间到期时,即使钩子还没有完成,JVM 也会退出。