摘要

记录Java优雅关闭的两种方式。

正文

Java优雅关闭的两种方式,源码地址

  1. 关闭应用后的回调
  2. 关闭应用前的信号监听

一、关闭应用的回调

通过关闭后的回调实现优雅关闭。

其实应用已经关闭了,只是在关闭时,回调启动一个线程执行。

java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
 * 通过关闭回调实现优雅关闭
 * 其实应用已经关闭了,只是在关闭时,回调启动一个线程执行
 *
 * @author chenchuancheng
 * @since 2023/2/23 10:04
 */
public class ByHook {

    public static void main(String[] args) throws Exception {
        //注册关闭后的回调hook
        registerHook();
        //模拟应用运行
        while (true) {
            Thread.sleep(1000);
            System.out.println("running...");
        }
    }

    public static void registerHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("通过Hook关闭: 其实应用已经关闭了,只是在关闭时,回调启动一个线程执行")));
    }


}

二、关闭应用前的信号监听

收到信号时,决定要进行的操作,如果不打算关闭,则对项目运行不影响。

java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import sun.misc.Signal;
import sun.misc.SignalHandler;

/**
 * 监听信号
 * 收到信号时,决定要进行的操作,如果不打算关闭,则对项目运行不影响。
 *
 * @author chenchuancheng
 * @since 2023/2/23 10:11
 */
public class BySignalHandler implements SignalHandler {

    public static void main(String[] args) throws Exception {
        //注册信号监听
        BySignalHandler handler = new BySignalHandler();
        Signal.handle(new Signal("TERM"), handler);
        Signal.handle(new Signal("INT"), handler);
        //模拟应用运行
        while (true) {
            Thread.sleep(1000);
            System.out.println("running...");
        }
    }


    @Override
    public void handle(Signal signal) {
        /**
         * SIGINT - 中断信号,通常是在用户按下 CTRL + C 时发送给前台进程的信号。
         * SIGTERM - 终止信号,通常是在需要正常终止进程时发送给进程的信号。
         */
        switch (signal.getName()) {
            case "INT":
                System.out.println("接收到命令 INT");
                break;
            case "TERM":
                System.out.println("接收到命令 TERM");
                break;
        }
    }
}