java 保证程序安全退出

以前在开发时只知道依靠数据库事务来保证程序关闭时数据的完整性。

但有些时候一个业务上要求的原子操作,不一定只包括数据库,比如外部接口或者消息队列。此时数据库事务就无能为力了。

这时我们可以依靠java提供的一个工具方法:java.lang.Runtime.addShutdownHook(Thread hook)

addShutdownHook方法可以加入一个钩子,在程序退出时触发该钩子。

(退出是指ctrl+c或者kill -15,但如果用kill -9 那是没办法的,具体有关kill的signal机制有篇大牛的文章《Linux 信号signal处理机制》

钩子做什么操作都可以,甚至可以循环检查某个线程的状态,直到业务线程正常退出,再结束钩子程序就可以保证业务线程的完整性

例子程序如下:

实例程序在执行过程中按下ctrl -c或者 kill -15,由于钩子程序的循环检测,能够保证线程执行完毕后,程序才关闭。

/**
 * Created by IntelliJ IDEA.
 * User: Luo
 * Date: 13-7-11
 * Time: 下午3:12
 */

public class TestShutdownHook {

    /**
     * 测试线程,用于模拟一个原子操作
     */
    private static class TaskThread extends Thread {
        @Override
        public void run() {
            System.out.println("thread begin ...");
            TestShutdownHook.sleep(1000);
            System.out.println("task 1 ok ...");
            TestShutdownHook.sleep(1000);
            System.out.println("task 2 ok ...");
            TestShutdownHook.sleep(1000);
            System.out.println("task 3 ok ...");
            TestShutdownHook.sleep(1000);
            System.out.println("task 4 ok ...");
            TestShutdownHook.sleep(1000);
            System.out.println("task 5 ok ...");

            System.out.println("thread end\n\n");
        }
    }

    /**
     * 注册hook程序,保证线程能够完整执行
     * @param checkThread
     */
    private static void addShutdownHook(final Thread checkThread) {
        //为了保证TaskThread不在中途退出,添加ShutdownHook
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("收到关闭信号,hook起动,开始检测线程状态 ...");
                //不断检测一次执行状态,如果线程一直没有执行完毕,超时后,放弃等待                       for (int i = 0; i < 100; i++) {
                    if (checkThread.getState() == State.TERMINATED) {
                        System.out.println("检测到线程执行完毕,退出hook");
                        return;
                    }
                    TestShutdownHook.sleep(100);
                }
                System.out.println("检测超时,放弃等待,退出hook,此时线程会被强制关闭");
            }
        });
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final TaskThread taskThread = new TaskThread();
        //为了保证TaskThread不在中途退出,添加ShutdownHook
        addShutdownHook(taskThread);
        //执行TaskThread
        taskThread.start();
    }

}

  

时间: 2024-08-11 03:34:18

java 保证程序安全退出的相关文章

java基础(死循环退出选项)

java程序中为了程序正常运行,需要给无限循环加入一个退出选项,保证程序的可执行性. import java.util.Scanner; public class { public static void main(String[] args) { Scanner scan = new Scanner(System.in); system.out.println("请输入您的操作选项"); int num = scan.nextInt(); switch (num) { case '1

使用 Acegi 保护 Java 应用程序

第 1 部分: 架构概览和安全过滤器 Acegi Security System 是一种功能强大并易于使用的替代性方案,使您不必再为 Java 企业应用程序编写大量的安全代码.虽然它专门针对使用 Spring 框架编写的应用程序,但是任何类型的 Java 应用程序都没有理由不去使用 Acegi.这份共分三部分的系列文章详细介绍了 Acegi,并展示了如何使用它保护简单的企业应用程序以及更复杂的应用程序. 本系列首先介绍企业应用程序中常见的安全问题,并说明 Acegi 如何解决这些问题.您将了解

Java并行程序基础总结

1-1 线程概念 1. 同步(Synchronous)和异步(Asynchronous) 2. 并发和并行 3. 临界区 4. 阻塞与非阻塞 5. 死锁.饥饿.活锁 6. 并发级别:阻塞.无饥饿.无阻碍.无锁.无等待 7. 并发的两个重要定律:Amdahl.Gustafson定律 2-1.线程的基本操作 2.1 创建线程 创建线程的第一种方式:继承Thread类. 步骤: 1,定义类继承Thread. 2,复写Thread类中的run方法. 目的:将自定义代码存储在run方法.让线程运行. 3,

java语言程序

第一章 Jave语言基础 1.1 Java语言的特点 领会Java语言的特点.关键字 1010-11.Java语言采用多种机制来保证可移植性,其中最主要的是______.虚拟机 1110-11.Java语言是一种 ____强类型语言___ 语言,它约束程序员必须遵守规定编写程序,能让编译器检测出程序中尽可能多的错误. 1.2 Java应用程序和小应用程序 识记      Java应用程序与小应用程序的特点和区别 11.一个应用程序必须在某个类中定义的方法是______.main() 1201-

【转】成为Java顶尖程序员 ,看这11本书就够了

成为Java顶尖程序员 ,看这11本书就够了 转自:http://developer.51cto.com/art/201512/503095.htm 以下是我推荐给Java开发者们的一些值得一看的好书.但是这些书里面并没有Java基础.Java教程之类的书,不是我不推荐,而是离我自己学习 Java基础技术也过去好几年了,我学习的时候看的什么也忘了,所以我不能不负责任地推荐一些我自己都没有看过的书给大家. 作者:来源:攻城狮之家|2015-12-31 09:55 收藏 分享 “学习的最好途径就是看

应用程序完全退出

前言 在Android应用程序的完全退出有点麻烦,系统没有提供完全退出的api. 退出单Activity程序 Android系统中提供了以下的方式来退出单Activity的应用程序,如下所示 Process.killProcess(Process.myPid()); System.exit(0); 退出多Activity程序 上一小节提到了退出单个Activity的方式,然而实际开发中很少有单个Activity的应用程序,而多个Activity的应用程序完全退出又不能直接退出,下面的方式通过记录

《Java应用程序(Application)》

1 在编写Java应用程序(Application)时可以这样: 2 3 1,定义包名. 4 2, 导入相关的包. 5 3, 定义一个类. 6 4,定义相关变量. 7 5,定义构造函数.(在构造函数内调用init()方法和addEvents()方法) 8 6, 在init()函数中组合各种组件. 9 7,在addEvents()方法中为各种组件添加事件监听器.(可以有异常的捕获及声明). 10 8,定义主函数.在主函数中创建一个本类的对象就可以了. 11 通过构造函数就可以完成调用程序的各种功能

Java应用程序高CPU故障诊断(troubleshooting)思路

系统运行出现高CPU报警,一般可以通过top或者任务管理器找到哪些进程在使用CPU,但这个粒度不能让我们知道得更多,我们需要找到程序的哪部分在占用CPU并且在占用CPU做什么,这样才有利于我们以后调优,下面介绍一种可行的思路: 找到占用CPU高的进程p 找到进程p中占用CPU高的线程t 找到线程t在做什么 本文以Linux下Java应用程序为例,其他环境或程序可参照该思路,只要思路清晰就好办了 打开top,在top中按shift+p按照CPU使用量倒序显示进程,找到占用CPU较高的进程号pid,

JAVA并行程序基础

JAVA并行程序基础 一.有关线程你必须知道的事 进程与线程 在等待面向线程设计的计算机结构中,进程是线程的容器.我们都知道,程序是对于指令.数据及其组织形式的描述,而进程是程序的实体. 线程是轻量级的进程,是程序执行的最小单位.(PS:使用多线程去进行并发程序的设计,是因为线程间的调度和切换成本远小于进程) 线程的状态(Thread的State类): NEW–刚刚创建的线程,需要调用start()方法来执行线程: RUNNABLE–线程处于执行状态: BLOCKED–线程遇到synchroni