想象一下,如果你现在刚好在 word 上写需求文档,电脑突然重启。等待开机完成,你可能会发现写了一个小时文档没有保存,就这么没了。。。

一个正在运行 Java 应用如果突然将其停止,影响不止数据丢失,还会造成其他影响。比如:

  • 请求丢失:内存队列中等待执行请求丢失
  • 数据丢失:处于内存缓存中数据未持久化到磁盘
  • 文件损坏:正在写的文件没有没有更新完成,导致文件损坏
  • 业务中断:处理一半的业务被强行中断,如支付成功了,却没有更新到数据库中
  • 服务未下线:上游服务依然往停止节点发送请求

所以在关闭服务之前,我们需要先做好善后工作,比如保存数据,清理资源,下线服务,然后才退出应用。这种有计划平滑的关闭应用相对直接停止应用,就显得非常『优雅』。

ps: 仔细品味,优雅停机这个词真好~

ShutdownHook

Java 语言提供一种 ShutdownHook(钩子)进制,当 JVM 接受到系统的关闭通知之后,调用 ShutdownHook 内的方法,用以完成清理操作,从而平滑的退出应用。

ShutdownHook代码如下:

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {System.out.println("关闭应用,释放资源");}));

Runtime.getRuntime().addShutdownHook(Thread) 需要传入一个线程对象,后续动作将会在该异步线程内完成。除了主动关闭应用(使用 kill -15 指令),以下场景也将会触发 ShutdownHook :

  • 代码执行结束,JVM 正常退出
  • 应用代码中调用 System#exit 方法
  • 应用中发生 OOM 错误,导致 JVM 关闭
  • 终端中使用 Ctrl C(非后台运行)

目前很多开源框架都是基于这个机制实现优雅停机,比如 Dubbo,Spring 等。

相关注意点

ShutdownHook 代码实现起来相对简单,但是我们还是需要小心下面这些坑。

Runtime.getRuntime().addShutdownHook(Thread) 可以被多次调用

我们可以多次调用 Runtime.getRuntime().addShutdownHook(Thread) 方法,从而增加多个。但是需要注意的是,多个 ShutdownHook 之间并无任何顺序,Java 并不会按照加入顺序执行,反而将会并发执行。

所以尽量在一个 ShutdownHook 完成所有操作。

ShutdownHook 需要尽快执行结束

不要在 ShutdownHook 执行需要被阻塞代码,如 I/0 读写,这样就会导致应用短时间不能被关闭。

 Runtime.getRuntime().addShutdownHook(new Thread(() -> {while (true){System.out.println("关闭应用,释放资源");}}));

上面代码中,我们使用 while(true) 模拟长时间阻塞这种极端情况,关闭该应用时,应用将会一直阻塞在 while 代码中,导致应用没办法被关闭。

除了阻塞之外,还需要小心其他会让线程阻塞的行为,比如死锁。

为了避免 ShutdownHook 线程被长时间阻塞,我们可以引入超时进制。如果等待一定时间之后,ShutdownHook 还未完成,由脚本直接调用 kill -9 强制退出或者 ShutdownHook 代码中引入超时进制。

文章首发于studyidea.cn

欢迎关注我的公众号:程序通事,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

ShutdownHook- Java 优雅停机解决方案相关推荐

  1. shutdown thread.java_ShutdownHook- Java 优雅停机解决方案

    想象一下,如果你现在刚好在 word 上写需求文档,电脑突然重启.等待开机完成,你可能会发现写了一个小时文档没有保存,就这么没了... 一个正在运行 Java 应用如果突然将其停止,影响不止数据丢失, ...

  2. java 优雅停机_spring boot2.0实现优雅停机的方法

    前期踩的坑 (spring boot 1.x) 1. 添加mavne依赖 org.springframework.boot spring-boot-starter-actuator 2. 启用shut ...

  3. dubbo protocol port 消费者端_Dubbo 优雅停机演进之路

    一.前言 在 『ShutdownHook- Java 优雅停机解决方案』 一文中我们聊到了 Java 实现优雅停机原理.接下来我们就跟根据上面知识点,深入 Dubbo 内部,去了解一下 Dubbo 如 ...

  4. springboot 优雅停机_Spring Boot 2.3 新特性优雅停机详解

    什么是优雅停机 先来一段简单的代码,如下: @RestControllerpublic class DemoController { @GetMapping("/demo") pu ...

  5. springboot 优雅停机_新姿势,Spring Boot 2.3.0 如何优雅停机?

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 来源 | https://urlify.cn/mu22If 先来一段简单的代码,如下: @RestControllerpub ...

  6. 【Java】优雅停机时的一点思考

    1.概述 转载:http://cxytiandi.com/blog/detail/15386 转载自:徐靖峰 Kirito的技术分享 最近瞥了一眼项目的重启脚本,发现运维一直在使用 kill -9 的 ...

  7. Java应用的优雅停机

    一. 优雅停机的概念 优雅停机一直是一个非常严谨的话题,但由于其仅仅存在于重启.下线这样的部署阶段,导致很多人忽视了它的重要性,但没有它,你永远不能得到一个完整的应用生命周期,永远会对系统的健壮性持怀 ...

  8. java signal handler_JAVA优雅停机的实现

    最近在项目中需要写一个数据转换引擎服务,每过5分钟同步一次数据.具体实现是启动engine server后会初始化一个ScheduledExecutorService和一个ThreadPoolExec ...

  9. java停机保存数据_哦,这就是java的优雅停机?(实现及原理)

    优雅停机?这个名词我是服的,如果抛开专业不谈,多好的名词啊! 其实优雅停机,就是在要关闭服务之前,不是立马全部关停,而是做好一些善后操作,比如:关闭线程.释放连接资源等. 再比如,就是不会让调用方的请 ...

  10. java唱歌打分系统原理_哦,这就是java的优雅停机?(实现及原理)

    优雅停机?这个名词我是服的,如果抛开专业不谈,多好的名词啊! 其实优雅停机,就是在要关闭服务之前,不是立马全部关停,而是做好一些善后操作,比如:关闭线程.释放连接资源等. 再比如,就是不会让调用方的请 ...

最新文章

  1. C语言中(字符串)输入scanf()、gets()、fgets()以及getchar()、getc()函数的联系与区别
  2. 绝了!Dataway让SpringBoot不在需要Controller、Service、DAO、Mapper了
  3. c++调用python的代码、函数、类
  4. 任务和特权级保护(二)——《x86汇编语言:从实模式到保护模式》读书笔记32
  5. linux权限体系有哪些角色,详解Linux下系统权限
  6. SecureWatch和人工智能为疫情期间更安全有效地监控房地产开发提供助力
  7. Maven入门指南:仓库
  8. Kafka学习(一)
  9. Ubuntu 18.04 软件源修改成国内源
  10. 编译的警告:隐式声明与内建函数 ‘malloc’ 不兼容
  11. spring教程笔记6
  12. 推荐10个最好用的数据采集工具
  13. Axure RP 8制作计时器
  14. 关于JavaScript中万恶的this
  15. 华为手机设置页面黑色_华为手机简单设置一下,来电直接显示对方照片视频,个性又炫酷...
  16. Excel基础操作(数据分析)归纳笔记
  17. 项目前期准备的重要性
  18. 六月回顾 | 盛夏已至,不负每一次期待
  19. 定制化centos7
  20. navicat设计表怎么给列加注释(简洁版)

热门文章

  1. U-BOOT 编译过程
  2. Mono 2.11.3 发布包含微软的 Entity Framework
  3. 关于jdk11没有jre
  4. java 中如何比较时间先后,java中如何进行日期时间比较?4种方法介绍
  5. python编写窗口怎么清除内容_如何删除或销毁tkinter中的标签?
  6. 拓端tecdat|TensorFlow 2建立神经网络分类模型——以iris数据为例
  7. AttributeError: module ‘tensorflow‘ has no attribute ‘ConfigProto‘
  8. python list()和[]的区别
  9. opencv如何获取图像的平均颜色
  10. keras(X_train, X_test, y_train, y_test)