Java应用程序退出的触发机制有:
1、自动结束:应用没有存活线程或只有后台线程时;
2、System.exit(0);
3、kill 或 ctrl+C;
4、kill -9 强制退出;
如何做到应用程序平滑停止
程序的退出就像关机一样,我们希望关机时平滑关机,保证所有应用程序的数据都保存了。就像现在在写得blog,希望关机的时候能被保存好到草稿箱里。
我们的的Java程序中经常有一种常驻的任务或服务,如消息消费端、服务提供者,我们期望停止也是平滑的不会出现事务执行到一半产生脏数据。
java对这块的支持是通过钩子线程实现。每个Java进程都可以注册钩子线程,钩子线程程在程序退出的前被执行(kill -9强制退出除外)。注册钩子线程代码如下:
Runtime.getRuntime().addShutdownHook(t);
我们可以在钩子线程里做一些善后数据清理等事情,以保证程序是平滑退出的。
一般服务或框架运行都要考虑其生命周期:
如spring容器的context.stop()方法。
再如线程池ExecutorService的shutdown方法,它会保证不接受新任务,并把未执行完的任务做完。
我们再设计服务的时候也要考虑到停止时的stop方法,以便于退出时由钩子线程调用。
注册了钩子线程后,程序收到退出信号后,会保持程序运行,直到钩子线程执行完毕,才把程序的所有线程停止并退出,下面示例代码可以说明这一点:
publicclassShutDownTest {
publicstaticvoidmain(String[] args) {
//注册第一个钩子
Runtime.getRuntime().addShutdownHook(newThread() {
publicvoidrun() {
try{
Thread.currentThread().sleep(5000);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("clean task1 completed.");
}
});
//注册第二个钩子
Runtime.getRuntime().addShutdownHook(newThread() {
publicvoidrun() {
try{
Thread.currentThread().sleep(10000);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("clean task2 completed");
}
});
//启动子线程
newThread() {
publicvoidrun() {
while(true) {
try{
Thread.currentThread().sleep(1000);
System.out.println("sub thread is running");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
//程序退出
System.exit(0);
}
}
31/3123>