在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码。Java中得ShutdownHook提供了比较好的方案。
  JDK在1.3之后提供了Java Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:

  • 1)程序正常退出
  • 2)使用System.exit()
  • 3)终端使用Ctrl+C触发的中断
  • 4)系统关闭
  • 5)使用Kill pid命令干掉进程

注:在使用kill -9 pid是不会JVM注册的钩子不会被调用。
在JDK中方法的声明:
public void addShutdownHook(Thread hook)
参数
hook -- 一个初始化但尚未启动的线程对象,注册到JVM钩子的运行代码。
异常
IllegalArgumentException -- 如果指定的钩已被注册,或如果它可以判定钩已经运行或已被运行
IllegalStateException -- 如果虚拟机已经是在关闭的过程中
SecurityException -- 如果存在安全管理器并且它拒绝的RuntimePermission(“shutdownHooks”)

代码示例:
使用Timer模拟一个工作线程,该线程重复工作十次,使用System.exit()退出,在清理现场代码CleanWorkThread 中,取消timer运行,并输出必要的日志信息。

package com.netease.test.java.lang;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger; /**
* Date: 14-6-18
* Time: 11:01
* 测试ShutdownHook
*/
public class TestShutdownHook { //简单模拟干活的
static Timer timer = new Timer("job-timer"); //计数干活次数
static AtomicInteger count = new AtomicInteger(0); /**
* hook线程
*/
static class CleanWorkThread extends Thread{
@Override
public void run() {
System.out.println("clean some work.");
timer.cancel();
try {
Thread.sleep(2 * 1000);//sleep 2s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
//将hook线程添加到运行时环境中去
Runtime.getRuntime().addShutdownHook(new CleanWorkThread());
System.out.println("main class start ..... ");
//简单模拟
timer.schedule(new TimerTask() {
@Override
public void run() {
count.getAndIncrement();
System.out.println("doing job " + count);
if (count.get() == 10) { //干了10次退出
System.exit(0);
}
}
}, 0, 2 * 1000); }
}

运行后,可以模拟以上五种场景进行测试,只有kill -9 pid不会执行Hook里面的代码。

Java应用中使用ShutdownHook友好地清理现场的更多相关文章

  1. Java应用中使用ShutdownHook友好地清理现场(转)

    在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.Java中得ShutdownHook提供了比较好的方案. JDK在1.3之后提 ...

  2. Java应用中使用ShutdownHook友好地清理现场、退出JVM的2种方法

    Runtime.getRuntime().addShutdownHook(shutdownHook);    这个方法的含义说明:        这个方法的意思就是在jvm中增加一个关闭的钩子,当jv ...

  3. Java 7 中 NIO.2 的使用——第四节 文件和目录

    Files类提供了很多方法用于检查在于你真正实际去操作一个文件或目录.这些方法强烈推荐,也非常有用,也能避免很多异常的发生.例如,一个很好的习惯就是在你试着移动一个文件从一个地方到另一个地方的时候,先 ...

  4. Java 17 将要发布,补一下 Java 13 中的新功能

    本文章属于Java 新特性教程 系列,已经收录在 Github.com/niumoo/JavaNotes ,点个赞,不迷路. 自从 Oracle 调整了 Java 的版本发布节奏之后,Java 版本发 ...

  5. Java编程中“为了性能”尽量要做到的一些地方

    最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源总结的一些在Ja ...

  6. 你的java 代码对JIT编译友好吗?

    JIT编译器是Java虚拟机(以下简称JVM)中效率最高并且最重要的组成部分之一.但是很多的程序并没有充分利用JIT的高性能优化能力,很多开发者甚至也并不清楚他们的程序有效利用JIT的程度. 在本文中 ...

  7. Java开发中常见的危险信号(中)

    本文来源于我在InfoQ中文站原创的文章,原文地址是:http://www.infoq.com/cn/news/2013/12/common-red-flags-in-java-1 Dustin Ma ...

  8. 你的Java代码对JIT编译友好么?(转)

    JIT编译器是Java虚拟机(以下简称JVM)中效率最高并且最重要的组成部分之一.但是很多的程序并没有充分利用JIT的高性能优化能力,很多开发者甚至也并不清楚他们的程序有效利用JIT的程度. 在本文中 ...

  9. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

随机推荐

  1. LinuxMint 18.3禁用ipv6

    编辑/etc/sysctl.conf文件,添加如下内容 net.ipv6.conf.all.disable_all = 1 保存后执行 sudo sysctl -p 即可生效

  2. vue 组件-组件定义的4种方式

    一.组件命名的方式 ①kebab-case,单词之间采用  - (短横线)连接,例如:my-component ,在DOM中使用时,<my-component ></my-compo ...

  3. JAVA之访问控制符

    1.访问修饰符 public:该类和非该类的均能访问 protect:该类和该类的子类,同一个包内的成员也能访问 默认:同一个包内的类可以访问 private:只有该类可以访问 特性:在继承的关系中, ...

  4. 【python 3.6】类:访问属性及调用方法

    >>> class price(): //定义1个类,用于计算价格 def __init__(self,name,danjia): //初始化方法,定义商品名称和单价 self.na ...

  5. React Native移动开发实战-2-如何调试React Native项目

    在实际开发中,还有一个影响开发效率的重要因素:调试. 在1.4.3节中已经介绍了Enable Live Debugger的使用.本节来介绍另一个非常重要的调试选项:Debug JSRemotely选项 ...

  6. python 输出格式化之后的时间格式

    import timetime.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

  7. vi/vim命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/mondol/p/vi-examples.html 进入vi vi filename # 打开或新建文件,并将光标置于第 ...

  8. python2.7 倒计时

    From: http://www.vitostack.com/2016/06/05/python-clock/#more Python公告 Python 发布了一个网站 http://pythoncl ...

  9. mysql/mybatis之合并两个表的查询结果

    下面这段sql是把两个表中各自符合条件的count值相加,返回结果是两个之和 SELECT sum(result) FROM ( SELECT COUNT(*) result FROM TEST_A ...

  10. 项目Beta冲刺(团队)总结

    团队成员及分工 姓名 学号 分工 陈家权 031502107 前端(消息模块) 赖晓连 031502118 前端(问答模块) 雷晶 031502119 服务器 林巧娜 031502125 前端(首页模 ...