优雅关闭项目
之前对java中的延迟任务进行了了解,但是对于实现延迟队列的一些方式(延迟队列,环形队列等),如果使用这些方式,在生产上,如果需要重启项目的话,那缓存中的数据如何进行保存,因此在网上搜罗了一些关于java优雅关闭的一些博客,即在ShutDownHook钩子函数中加入一些将延迟队列中的数据存储起来的方法
Linux的信号机制
kill命令可将指定的信号发送给相应的进程,linux中常见的信号如下:
1 SIGHUP 挂起进程
2 SIGINT 终止进程
3 SIGGQUIT 停止进程
9 SIGKILL 无条件终止进程
15 SIGTERM 尽可能终止进程
17 SIGSTOP 无条件停止进程,但不是终止
18 SIGTSTP 停止或者暂停进程,但不终止进程
19 SIGCONT 继续运行停止的进程
默认情况下kill命令使用的是
kill -15,此时,如果java程序中定义的shutDownHook时,会触发; 如果使用kill -9则不会触发钩子
- 1、ShutDownHook函数
/**
 * cmd执行javac 编译后  使用java执行class文件
 *   执行了 java TestShutDownHook  之后,输出“main executing”
 *   但按 Ctrl+c之后,会输出shutDownHook execute
 *   此时代表钩子函数执行了
 */
public class TestShutDownHook {
    public static void main(String[] args) {
        System.out.println("main executing");
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("shutDownHook execute");
        }));
        try {
            TimeUnit.DAYS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
以上代码在linux系统中执行 kill -15 test.jar 时,会回调ShutDownHook方法
- 2、springboot中的ShutDownHook
springboot项目中可以在自定义Bean对象,在启动时,添加ShutDownHook
package com.xsxy.alltestproject.springbootShutDownHook;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class SpringbootShutDownHook {
    @PostConstruct
    public void registerShutDownHook(){
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("springboot execute shutdownhook");
        }));
    }
}
测试:
打出jar包后,使用java -jar test.jar 启动springboot项目
nohup java -jar all-test-project-0.0.1-SNAPSHOT.jar &
-->
[1] 6641
使用kill -15 终止进程,会将springboot execute shutdownhook日志输出到nohup文件中
而使用kill -9时,并不会调用ShutDownHook的方法
以下为网上的案例未经过测试:
- 3、 实现SignalHandler
public class KillHandler implements SignalHandler {  
  
    public void registerSignal(String signalName) {  
        Signal signal = new Signal(signalName);  
        Signal.handle(signal, this);  
    }  
  
    @Override  
    public void handle(Signal signal) {  
         
        if (signal.getName().equals("TERM")) {  
                //  
        } else if (signal.getName().equals("INT") || signal.getName().equals("HUP")) {  
                //  
        } else {  
                //  
        }  
    }  
  
} 
 程序启动时实例化一个KillHandler,注册TERM信号。
 KillHandler killHandler = new KillHandler();
 killHandler.registerSignal(“TERM”);
 这样,在进程被kill的时候就会触发KillHandler的handle方法。
相关博客 https://blog.csdn.net/u011001084/article/details/73480432 https://blog.csdn.net/m0_37793798/article/details/84206167 https://blog.csdn.net/chinrui/article/details/78685032

 
 
        
         
      
 
                 
                
