java 关闭勾子的使用方法

1、最佳位置(main 方法起始处)

确保可靠性:即使后续代码抛出异常,关闭钩子已注册
避免竞态条件:防止在注册前就收到关闭信号

public class App {
    public static void main(String[] args) {
        // 1. 最先注册关闭钩子(确保一定能被执行)
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("正在关闭资源...");
            PooledProducer.shutdown();  //这句是ActiveMQ关闭函数,就是个示例,
            //这里写程序关闭时需要执行的代码

        }));

        //下面写业务逻辑代码
} }

 2、关闭钩子的触发场景

触发方式是否能执行关闭钩子示例
正常退出 ✅ 能 System.exit(0)
Ctrl+C ✅ 能 控制台中断
kill -15 ✅ 能 kill -15 <pid>
kill -9 ❌ 不能 强制杀死进程
JVM崩溃 ❌ 不能 OutOfMemoryError
系统关机 ✅ 能 Linux shutdown -h now

  3、增强版实现(带超时控制)

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    System.out.println("接收到关闭信号,开始优雅停止...");
    
    long start = System.currentTimeMillis();
    PooledProducer.shutdown(); // 关闭生产者 这句是示例,需要写 在程序关闭要执行的代码
    
    // 等待线程池终止(最多10秒)
    try {
        if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
            System.err.println("强制终止未完成任务");
            executor.shutdownNow();
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    
    System.out.printf("关闭完成,耗时 %dms%n", System.currentTimeMillis() - start);
}));

注:避免死锁

不要在关闭钩子中执行耗时操作(如等待网络响应)
设置合理的超时时间(如10秒)

 

posted @ 2025-08-06 12:53  海乐学习  阅读(14)  评论(0)    收藏  举报