过程记录
代码中在shutdown hook的过程中有使用到System.exit(1);但无法正确退出。
在使用关闭钩子还要注意以下几点:
- 不能在钩子调用System.exit(),否则卡住JVM的关闭过程,但是可以调用Runtime.getRuntime().halt(1)。
- 不能再钩子中再进行钩子的添加和删掉操作,否则将会抛出IllegalStateException。
- 在System.exit()之后添加的钩子无效。
- 当JVM收到SIGTERM命令(比如操作系统在关闭时)后,如果钩子线程在一定时间没有完成,那么Hook线程可能在执行过程中被终止。
- Hool线程中同样会抛出异常,如果抛出异常又不处理,那么钩子的执行序列就会被停止。
摘自:https://juejin.im/entry/57a3fc818ac247005f19edf5
有一个shutdown hook的线程threadA无法退出:
线程调用了threadB.join();
threadB的run代码段如下:
Object data = null;
while (true) {
if (stop) {
data = blockingQueue.poll();
} else {
try {
data = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (data != null) {
// do something
} else if (stop){
break;
}
}
很明显了,BlockingQueue.take() 会一直等待直到获取到数据,又由于threadA,调用了threadB.join(),所以线程A无法正常结束。
bug fix:
将上面的
data = blockingQueue.take();
改为:
data = blockingQueue.poll(1, TimeUnit.SECONDS);
改后发现处理有异常,导致没有正确处理后续,加入catch。
后面发现shutdown hook中有System.exit(1),导致无法关闭,删除之。