首先说明这个
Runtime.getRuntime().addShutdownHook(new Thread())
方法是用来捕捉程序退出的时刻,在程序退出的时候处理必要的退出准备,如关闭网路,关闭文件等。
那对于我们来讲,我们平时是怎么退出程序的,正常来讲是让程序正常退出,或者执行
System.exit(0)
来结束程序,我们来演示一下:
package runtimetest;
public class Test {
public static void main(String[] args) {
ExitTest exitTest=new ExitTest();
exitTest.et();
System.out.println("程序正常退出");
// System.exit(-10);//这里相当于指定状态,如果不适用这一句,默认状态是0
}
}
class ExitTest{
public void et(){
System.out.println("这是一个退出程序");
}
}
- 这里是执行之后的结果:
上述的方法可以实现程序退出操作,但是当我们使用多线程的时候,或者在实际业务中我们难知道程序是什么时候结束的,但是又很需要捕捉程序退出的一刻对程序进行必要处理,
java提供了一个程序退出处理机制:Runtime.getRuntime().addShutdownHook(new Thread())
,首先通过Runtime.getRuntime()
获得当前的程序对象(这是一个静态方法),然后通过Runtime中的void addShutdownHook(Thread hook)
方法来向java的虚拟机(JVM)注册一个shutdown的钩子事件,这样程序一旦结束,就会运行线程hook。在实际业务中,我们只需要将程序结束之前需要做的一些工作放在线程hook来完成就可以了。下面我们来演示一下:
package runtimetest;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
public class ShutdownHookTest {
//构造方法
public ShutdownHookTest(){
doShutdownWork();
}
private void doShutdownWork(){
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
System.out.println("打印处理的时间:"+(end - start));
} catch (Exception e) {
}
}));
Runtime.getRuntime().addShutdownHook(new Thread(()->{
try {
System.out.println("这里执行程序退出前的处理程序");
} catch (Exception e) {
e.printStackTrace();
}
}));
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
//写到日志文件
FileWriter fw = new FileWriter("E://ideaworkspace//src//runtimetest//t.log");
System.out.println("I'm going to end");
fw.write("the application ended! " + (new Date()).toString());
fw.close();
}
catch (IOException ex) {
}
}
});
}
}
- 这里是测试程序,这里只是建立一个处理程序的对象,而不需要直接调用具体处理退出程序的方法,就可以实现退出程序前对程序处理
package runtimetest;
public class Test {
public static void main(String[] args) {
ShutdownHookTest shutdownHookTest=new ShutdownHookTest();
long start =System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
System.out.print(i+" ");
}
long end =System.currentTimeMillis();
System.out.println();
System.out.println("main"+(end-start));
}
}
就好比我实例的一样,我们的关机构可以不只是一个,可以同时注册多个关机构,在JVM退出之前,它会启动所有的已注册的关机构,并且让这些关机构同步执行
shutdownhook(关机钩)的主要目的是在系统中断后进行必要的清除,例如进行网络关闭、关闭打开的文件等操作,可以通过在一个关机钩执行之前可以使用removeShutdownHook()来删除一个已注册的关机钩,也可以调用halt()不调用关机钩线程直接退出JVM。