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

  在线上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里面的代码。

http://www.cnblogs.com/nexiyi/p/java_add_ShutdownHook.html

时间: 2024-10-25 13:17:52

Java应用中使用ShutdownHook友好地清理现场(转)的相关文章

Java应用中使用ShutdownHook友好地清理现场

在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.Java中得ShutdownHook提供了比较好的方案. JDK在1.3之后提供了Java Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用: 1)程序正常退出 2)使用System.exit() 3)终端使用Ctrl+C触发的中断 4)系统关闭 5)使用Kill pid命令干掉进程

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

Files类提供了很多方法用于检查在于你真正实际去操作一个文件或目录.这些方法强烈推荐,也非常有用,也能避免很多异常的发生.例如,一个很好的习惯就是在你试着移动一个文件从一个地方到另一个地方的时候,先检查文件是否存在. 检查一个文件或目录是否存在 在前面的例子中已经演示到,Path实例能够有效的映射到一个文件或是目录甚至这个文件或目录物理上根本不存在.再是,Path的很多方法不会实际操作文件本身就能成功地应用.所以,事先判断一个目录或是文件存在就显得非常重要.下面有两个方法用来判断文件是否存在.

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

下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方. 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步来控制资源的并发访问: 第二,控制实例的产生,以达到节约资源的目的: 第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信. 2. 尽量避免随意使用静态变量 要知道,当某个对象被定义为stataic变量所

java编程中'为了性能'一些尽量做到的地方

java编程中'为了性能'一些尽量做到的地方 2011-08-16 14:34:59|  分类: JAVA |  标签:java编程  缓存经常使用的对象  |举报|字号 最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方- 1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并

Eclipse对于多个Java项目的支持并不友好!

本文吐槽! 假设我们创建两个Java项目,一个叫StatsReader,把数据从网上下载到本地数据库里:一个叫StatsViewer,把数据从数据库里拿出来呈现给用户.这两个项目都要用同一个外部类库mysql-connector-java-5.0.8-bin.jar. Eclipse可以创建一个工作集,内含多个Java项目,但工作集只是一个概念,与项目的实际存储位置无关.但是我们可以把两个项目放在同一个目录里,比如D:\Source Code\NBA\StatsReader和D:\Source

java编程中的性能提升问题

java编程中的性能提升 软件产品犹如一栋大楼,大楼在建设初期,会有楼房规划,建筑构想,打牢地基,后面才是施工人员进行进行实质性的建设.要保证软件产品的高质量,优秀的架构,优秀的产品设计,是产生高质量的前提.同时,没有过硬的编码实现,一样得不到预期的效果.纵观现在的产品,产品架构没多大差别,基本运用基线版本进行局点定制.而系统中的一些功能性能常常不过关,问题往往就出在编码实现上.这块是开发人员在开发过程中需要注意的.在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良

避免在Java+接口中使用数组的3个理由

转帖: http://eclipsesource.com/blogs/2014/04/11/3-good-reasons-to-avoid-arrays-in-java-interfaces/ 如果你发现在一个接口使用有如下定义方法: public String[] getParameters(); 那么你应该认真反思.数组不仅仅老式,而且我们有合理的理由避免暴露它们.在这篇文章中,我将试图总结在Java API中使用数组的缺陷.首先从最出人意料的一个例子开始. 数组导致性能不佳 你可能认为使用

java学习中,面向对象的三大特性:封装、继承、多态 以及 super关键字和方法的重写(java 学习中的小记录)

java学习中,面向对象的三大特性:封装.继承.多态 以及 super关键字和方法的重写(java 学习中的小记录) 作者:王可利(Star·星星) 封装     权限修饰符:public 公共的,private 私有的     封装的步骤:          1.使用private 修饰需要封装的成员变量.          2.提供一个公开的方法设置或者访问私有的属性              设置 通过set方法,命名格式:     set属性名();  属性的首字母要大写 访问 通过ge

你的Java代码对JIT编译友好么?

JIT编译器是Java虚拟机(以下简称JVM)中效率最高并且最重要的组成部分之一.但是很多的程序并没有充分利用JIT的高性能优化能力,很多开发者甚至也并不清楚他们的程序有效利用JIT的程度. 在本文中,我们将介绍一些简单的方法来验证你的程序是否对JIT友好.这里我们并不打算覆盖诸如JIT编译器工作原理这些细节.只是提供一些简单基础的检测和方法来帮助你的代码对JIT友好,进而得到优化. JIT编译的关键一点就是JVM会自动地监控正在被解释器执行的方法.一旦某个方法被视为频繁调用,这个方法就会被标记