Java关闭挂钩– Runtime.addShutdownHook()
程序退出时,使用Java shutdown钩子可以方便地运行一些代码。
我们可以使用java.lang.Runtime.addShutdownHook(Thread t)方法在JVM中添加一个关闭钩子。
Java关闭钩子
在这两种情况下都将运行Java shutdown hook。
程序正常退出,或者我们调用
System.exit()方法终止程序。
阅读有关Java系统类的更多信息。用户中断,例如Ctrl + C,系统关闭等。
有关Java Shutdown Hook的要点是:
我们可以使用Runtime的addShutdownHook()方法添加多个关闭钩子。
关闭挂钩是已初始化但未启动的线程。
它们在JVM关闭触发时启动。我们无法确定关机挂钩的执行顺序,就像执行多线程一样。
如果已启用退出完成,则将执行所有未调用的终结器。
无法保证关机钩子会执行,例如系统崩溃,kill命令等。
因此,仅应将其用于紧急情况下,例如确保释放关键资源等。您可以使用Runtime.getRuntime()。
removeShutdownHook(hook)方法删除钩子。启动关闭挂钩后,将无法删除它们。
您将得到IllegalStateException。如果存在安全管理器并且它拒绝
RuntimePermission(" shutdownHooks"),则将获得SecurityException。
Java关闭挂钩示例
因此,让我们来看一下Java中的shutdown钩子示例。
这是一个简单的程序,其中我从某个目录中逐行读取文件并进行处理。
我将程序状态保存在静态变量中,以便关机挂钩可以访问它。
package com.theitroad.shutdownhook;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
public class FilesProcessor {
public static String status = "STOPPED";
public static String fileName = "";
public static void main(String[] args) {
String directory = "/Users/hyman/temp";
Runtime.getRuntime().addShutdownHook(new ProcessorHook());
File dir = new File(directory);
File[] txtFiles = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if (name.endsWith(".txt"))
return true;
else
return false;
}
});
for (File file : txtFiles) {
System.out.println(file.getName());
BufferedReader reader = null;
status = "STARTED";
fileName = file.getName();
try {
FileReader fr = new FileReader(file);
reader = new BufferedReader(fr);
String line;
line = reader.readLine();
while (line != null) {
System.out.println(line);
Thread.sleep(1000); //assuming it takes 1 second to process each record
//read next line
line = reader.readLine();
}
status = "PROCESSED";
} catch (IOException | InterruptedException e) {
status = "ERROR";
e.printStackTrace();
}finally{
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
status="FINISHED";
}
}
上面代码中最重要的部分是第16行,我们其中添加了shutdown钩子,下面是实现类。
package com.theitroad.shutdownhook;
public class ProcessorHook extends Thread {
@Override
public void run(){
System.out.println("Status="+FilesProcessor.status);
System.out.println("FileName="+FilesProcessor.fileName);
if(!FilesProcessor.status.equals("FINISHED")){
System.out.println("Seems some error, sending alert");
}
}
}
这是一种非常简单的用法,我只是在记录关闭钩子启动时的状态,如果还没有完成,则发送警报(实际上不是在这里记录它)。
让我们看看通过终端执行一些程序。
程序使用Ctrl + C命令终止。
如上图所示,当我们尝试使用Ctrl + C命令杀死JVM时,shutdown hook开始执行。程序正常执行。
请注意,即使在正常退出的情况下,钩子也会被调用,并且打印状态为完成。Kill Command终止JVM。
我使用了两个终端窗口向Java程序发射kill命令,因此操作系统终止了JVM,在这种情况下,未执行关闭钩子。

