博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 平滑 停止_设计Java应用程序的平滑停止
阅读量:6266 次
发布时间:2019-06-22

本文共 3612 字,大约阅读时间需要 12 分钟。

Java 应用程序退出的触发机制有: 1、自动结束:应用没有存活线程或只有后台线程时; 2、System.exit(0); 3、kill 或 ctrl+C; 4、kill -9 强制退出; 如何做到应用程序平滑停止 程序的退出就像关机一样,我们希望关机时平滑关机,保证所有应用程序的数据都

Java应用程序退出的触发机制有:

1、自动结束:应用没有存活线程或只有后台线程时;

2、System.exit(0);

3、kill 或 ctrl+C;

4、kill -9 强制退出;

如何做到应用程序平滑停止

程序的退出就像关机一样,我们希望关机时平滑关机,保证所有应用程序的数据都保存了。就像现在在写得blog,希望关机的时候能被保存好到草稿箱里。

我们的的Java程序中经常有一种常驻的任务或服务,如消息消费端、服务提供者,我们期望停止也是平滑的不会出现事务执行到一半产生脏数据。

java对这块的支持是通过钩子线程实现。每个Java进程都可以注册钩子线程,钩子线程程在程序退出的前被执行(kill -9强制退出除外)。注册钩子线程代码如下:

Runtime.getRuntime().addShutdownHook(t);

我们可以在钩子线程里做一些善后数据清理等事情,以保证程序是平滑退出的。

一般服务或框架运行都要考虑其生命周期:

如spring容器的context.stop()方法。

再如线程池ExecutorService的shutdown方法,它会保证不接受新任务,并把未执行完的任务做完。

我们再设计服务的时候也要考虑到停止时的stop方法,以便于退出时由钩子线程调用。

注册了钩子线程后,程序收到退出信号后,会保持程序运行,直到钩子线程执行完毕,才把程序的所有线程停止并退出,下面示例代码可以说明这一点:

public class ShutDownTest {

public static void main(String[] args) {

//注册第一个钩子

Runtime.getRuntime().addShutdownHook(new Thread() {

public void run() {

try {

Thread.currentThread().sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("clean task1 completed.");

}

});

//注册第二个钩子

Runtime.getRuntime().addShutdownHook(new Thread() {

public void run() {

try {

Thread.currentThread().sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("clean task2 completed");

}

});

//启动子线程

new Thread() {

public void run() {

while (true) {

try {

Thread.currentThread().sleep(1000);

System.out.println("sub thread is running");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

//程序退出

System.exit(0);

}

}

程序输出:

sub thread is running

sub thread is running

sub thread is running

sub thread is running

clean task1 completed.

sub thread is running

sub thread is running

sub thread is running

sub thread is running

sub thread is running

clean task2 completed

注意点:钩子线程里只处理善后,目标是尽可能快的退出且不保证有脏数据。如果钩子线程里做过多事情,或者发生阻塞,那么可能出现kill失效,程序不能退出的情况,这是需要强制退出。

如以下程序会导致kill失效,需要强制退出,因为钩子线程阻塞了:

public class ShutDownTest {

public static void main(String[] args) {

//注册钩子

Runtime.getRuntime().addShutdownHook(new Thread() {

public void run() {

synchronized (ShutdownFileTest.class) {

try {

ShutdownFileTest.class.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

//启动子线程

new Thread() {

public void run() {

while (true) {

try {

Thread.currentThread().sleep(1000);

System.out.println("sub thread is running");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

System.exit(0);

}

}

程序退出机制选择

触发程序退出的在前面已经提到过,但是为了停止方便、安全和优雅,一般我们推荐几种操控性更强的退出机制。常见的推荐机制有以下几种:

1.kill

在linux里用的比较多,向进程发送退出信号,java进程收到后平滑退出。

2.shutdownfile

系统创建一个shutdown file.并监听shutdown file是否存在。如果发现shutdown file不存在了,那么调用System.exit,将程序退出。

如果期望只有特定的人才能终止该程序,那么你可以给文件设定权限,这样就只有特定的人可以终止程序。

以下代码是个简单的例子:

import java.io.File;

import java.io.IOException;

public class ShutdownFileTest {

public static void main(String[] args) {

// 启动子线程

new Thread() {

public void run() {

while (true) {

try {

Thread.currentThread().sleep(1000);

System.out.println("sub thread is running");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

//启动shutdownfile监听线程

new Thread() {

public void run() {

File shutDownFile = new File("a.shutdown");

// create shut down file

if (!shutDownFile.exists()) {

try {

shutDownFile.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

// watch for file deleted then shutdown

while (true) {

try {

if (shutDownFile.exists()) {

Thread.currentThread().sleep(1000);

} else {

System.exit(0);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

}

}

3.打开一个端口,监听端口里的命令,收到命令后调用System.exit。

这个似乎不常见,也比较麻烦。

4.JMX

通过JMX的mbean远程控制来实现。

转载地址:http://dxspa.baihongyu.com/

你可能感兴趣的文章
只有PD号的调起
查看>>
返回一个整数数组中最大子数组的和
查看>>
leetcode(二)
查看>>
利用css实现居中的方法
查看>>
Spring + Hibernate 框架
查看>>
添加浏览器的用户样式表
查看>>
LigerUI学习笔记之布局篇 layout
查看>>
LeetCode题解(二)
查看>>
Mybatis通用Mapper
查看>>
文件磁盘命令(就该这么学6章内容)
查看>>
2016-207-19 随笔
查看>>
java的double类型如何精确到一位小数?
查看>>
看看国外的javascript题目,你能全部做对吗?
查看>>
ffmpeg 如何选择具有相同AVCodecID的编解码器 (AVCodec)
查看>>
真正解决 Windows 中 Chromium “缺少 Google API 密钥” 的问题
查看>>
Spring 之 AOP
查看>>
软件项目管理|期末复习(二)
查看>>
直接调用VS.net2005中的配置界面
查看>>
程序员的自我修养五Windows PE/COFF
查看>>
关于字符集,编码格式,大小端的简单总结
查看>>