当前位置: 首页 > news >正文

java 平滑 停止_设计Java应用程序的平滑停止

Java应用程序退出的触发机制有:自动结束:应用没有存活线程或只有后台线程时;

System.exit(0);

kill 或 ctrl+C;

kill -9 强制退出;

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

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

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

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

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

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

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

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

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

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

publicstaticvoidmain(String[] args) {

//注册第一个钩子

Runtime.getRuntime().addShutdownHook(newThread() {

publicvoidrun() {

try{

Thread.currentThread().sleep(5000);

}catch(InterruptedException e) {

e.printStackTrace();

}

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

}

});

//注册第二个钩子

Runtime.getRuntime().addShutdownHook(newThread() {

publicvoidrun() {

try{

Thread.currentThread().sleep(10000);

}catch(InterruptedException e) {

e.printStackTrace();

}

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

}

});

//启动子线程

newThread() {

publicvoidrun() {

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失效,需要强制退出,因为钩子线程阻塞了:publicclassShutDownTest {

publicstaticvoidmain(String[] args) {

//注册钩子

Runtime.getRuntime().addShutdownHook(newThread() {

publicvoidrun() {

synchronized(ShutdownFileTest.class) {

try{

ShutdownFileTest.class.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

});

//启动子线程

newThread() {

publicvoidrun() {

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,将程序退出。

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

以下代码是个简单的例子:importjava.io.File;

importjava.io.IOException;

publicclassShutdownFileTest {

publicstaticvoidmain(String[] args) {

// 启动子线程

newThread() {

publicvoidrun() {

while(true) {

try{

Thread.currentThread().sleep(1000);

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

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

//启动shutdownfile监听线程

newThread() {

publicvoidrun() {

File shutDownFile =newFile("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远程控制来实现。

在这个链接里有看到例子:how-to-stop-java-process-gracefully

原文链接:http://singleant.iteye.com/blog/1441219

【编辑推荐】深入Java探索:Java内存区域

同一段程序在Java和C中的不同结果

Java中Runnable和Thread的区别

Java对存储过程的调用方法

Java初学者都必须理解的六大问题

推荐阅读

最近有空,用Java写了个A*搜索,并使用swing做为显示。关于算法知识,可以在这里查到(http://en.wikipedia.org/wiki/A*_search_algorithm),其它网站也有很多介绍。我就不说了。本文主要提供源码下载和一些测试数据。>>>详细阅读

地址:http://www.17bianji.com/kaifa2/Java/914.html

相关文章:

  • java开发按键精灵_Java 按键精灵
  • java同步开销_java – 为什么对Map的同步访问会增加大量的开销
  • java字节码常量池_Java字节码常量池深度剖析与字节码整体结构分解
  • java控制语句案例_Java基础之流程控制(示例代码)
  • mysql 怎么设置ip地址_Mysql如何设置用户指定ip地址操作数据库
  • android_iphone和java三个平台一致的加密方法_Android、iPhone和Java三个平台一致的加密工具...
  • java最崇拜谁_蓝桥杯(java)个人赛真题:小朋友崇拜圈
  • java数组函数结局实际问题_java函数与数组
  • java登录字符串封装_JAVA的随机的字符串的封装(基本上够用了)
  • java统一管理文字_为了统一管理组件和容器,Java为所有组件类定义的超类
  • django mysql 分表_Django数据库分表
  • php aws_Amazon S3 客户端加密与 AWS SDK for PHP 版本 3 - 适用于 PHP 的 AWS 开发工具包...
  • Php公钥加密data是空,实用的PHP带公钥加密类分享(每次加密结果都不一样哦)
  • java做节奏大师,《节奏大师》高手必修之路 亲测攻略_iOS游戏频道_97973手游网
  • 注册php tp5,thinkphp5 开发会员注册与登录功能
  • [NodeJS] 关于Buffer
  • 【剑指offer】让抽象问题具体化
  • angular组件开发
  • axios 和 cookie 的那些事
  • docker-consul
  • happypack两次报错的问题
  • java8 Stream Pipelines 浅析
  • Js基础知识(一) - 变量
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • nodejs实现webservice问题总结
  • WePY 在小程序性能调优上做出的探究
  • 对象管理器(defineProperty)学习笔记
  • - 概述 - 《设计模式(极简c++版)》
  • 区块链共识机制优缺点对比都是什么
  • 线性表及其算法(java实现)
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 转载:[译] 内容加速黑科技趣谈
  • AI算硅基生命吗,为什么?
  • Linux权限管理(week1_day5)--技术流ken
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​io --- 处理流的核心工具​
  • ​卜东波研究员:高观点下的少儿计算思维
  • #stm32整理(一)flash读写
  • #Z2294. 打印树的直径
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (C)一些题4
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (汇总)os模块以及shutil模块对文件的操作
  • (四)库存超卖案例实战——优化redis分布式锁
  • (未解决)macOS matplotlib 中文是方框
  • ... 是什么 ?... 有什么用处?
  • .NET Framework .NET Core与 .NET 的区别
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .NET 常见的偏门问题
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .skip() 和 .only() 的使用
  • @SuppressWarnings(unchecked)代码的作用
  • [ C++ ] 继承
  • [2021ICPC济南 L] Strange Series (Bell 数 多项式exp)