JVM优雅停机

JVM优雅停机


介绍

最近在看公司自己封装的Dubbo组件时,看到了一段感觉笔者觉得很棒的代码,是利用了JVM的优雅停机机制,这里记录一下。

源码

public class Provider{
  private final static Object MONITOR = new Object();
  
  public void start() throws Exception{
    registerHook();
    doStart();
    waitShutdown();
  }
  
  protected void doStart(){
    // 启动加载逻辑
  }
  
  public void shutdown(){
    // 关闭逻辑
  }
  
  private void registerHook(){
    // 	注册关闭钩子事件
      Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
            public void run() {
                System.out.println("shutdown hook!");
                Provider.this.shutdown();
            }
        });
  }
  
  private void waitShutdown() throws Exception{
    synchronized(MONITOR){
      MONITOR.wait();
    }
  }
}

分析

上面贴出来的代码主要有2个关注点:

  • wait方法会一直阻塞等待被唤醒,或者程序终止
  • JVM钩子事件可以帮助我们在程序结束时完成一些关闭资源的操作

因为本次的重点是JVM钩子函数,所以接下来就来了解一下它

JVM钩子

JVM的作用

我们经常在程序终止的时候会碰到这样的情况:

  • 缓存中的数据尚未持久化到磁盘中,导致数据丢失;

  • 正在进行文件的write操作,没有更新完成,突然退出,导致文件损坏;

  • 线程池的任务队列中尚有接收到的任务还没来得及处理,导致任务丢失;

  • 数据库操作已经完成,例如账户余额更新,准备返回应答消息给客户端时,消息尚在通信线程的发送队列中排队等待发送,进程强制退出导致应答消息没有返回给客户端,客户端发起超时重试,会带来重复更新问题;

  • 其它问题等…

    此时我们希望程序在正常退出前可以做一些类似的前置动作,而jvm钩子就是Java提供给我们的接口,让我们在程序正常结束前完成一些自定义的逻辑。

如何使用

我们可以通过Runtime.getRuntime().addShutdownHook()完成钩子函数的注入,就像这样:

Runtime.getRuntime().addShutdownHook(new Thread(){
  @Override
  public void run(){
    // 业务逻辑
  }
});

这样当程序正常停止时,可以执行相应的逻辑,例如:关闭连接池,线程池,处理未完成的业务,等等。从而达到优雅停机的目的。

钩子函数一定会执行吗

细心的读者可能已经发现,我在描述钩子函数的执行时机时,一直强调的是程序正常停止那么什么是正常停止呢?

在这里插入图片描述

此图来自于JVM安全退出, 我想上面的图已经表达清楚了什么是正常的关闭程序,所以我们在编写停机脚本时应带采用kill -TERM而非kill -9去杀死程序,从而让我们的钩子函数得以执行。

参考:新达达技术-JVM安全退出

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值