java 后台跳出提示_Linux系统下如何优雅地关闭Java进程?

前言

Linux系统下如何kill掉一个后台Java进程,相信童鞋们都知道如何操作。首先使用ps命令查找该Java进程的进程ID,然后使用kill命令进行杀掉。命令如下:

(1)ps查进程ID

[user@data2 ~]$ ps -ef | grep Test

user 20950 20809 0 21:30 pts/1 00:00:00 java -jar Test.jar

user 21030 20996 0 21:30 pts/2 00:00:00 grep Test

(2)kill杀进程

[user@data2 ~]$ kill -9 20950

再使用ps命令查该进程,发现进程Test.jar已经被杀掉。使用“kill -9 $pid”杀Java进程,干净利落。但该方法是不是结束Java后台进程的较好方法呢?

场景

思考下面的场景:

“开发一个Java后台程序,其功能是不停地扫描Linux系统下的某个ftp目录。如果有文件,就经过数据转换写入到数据库中;如果没有文件,就sleep一秒钟。ftp目录下的文件不断地上传,Java程序处理完一个文件,就将该文件移到备份目录下面。”

该场景涉及Java程序进行文件打开、文件读取、文件备份、数据库连接、数据库写入等操作。因为文件句柄和数据库连接在Linux系统中是有限的资源,所以文件和数据库操作完成,需要进行关闭。

如果用户直接使用“kill -9”杀掉一个后台正在读取文件并写入数据库的Java进程。那么有可能文件和数据库连接没有正确关闭,而且数据文件也没有标识是否处理完成,或处理到哪个位置。

应用

近日在处理分布式消息Kafka的消息读取的工作,同样面临着上述场景的问题。如果读取了一条消息,在处理该消息之前进程被用户强行杀掉。那么该条消息就丢失了,既不在消息队列,也不在数据库或本地文件中。所以需要让后台Java进程在被杀的时候得到通知,这样就能安排好进程的“后事”。

Java中要得到kill信号通知,需要继承自“SignalHandler”类。完整实现代码如下:

import sun.misc.Signal;

import sun.misc.SignalHandler;

publicclass Engine implements SignalHandler {

privateboolean beKilling =false;

publicstaticvoid main(String[] args){

Engine signalHandler =new Engine();

Signal.handle(new Signal("TERM"), signalHandler); // kill -15

Signal.handle(new Signal("INT"), signalHandler); // Ctrl+c

Signal.handle(new Signal("USR2"), signalHandler); // kill -12

String zookeeper ="host1:2181,host2:2181,host3:2181";

String groupId ="gp01";

String topic ="test";

KafkaConsumer kc =new KafkaConsumer(zookeeper, groupId, topic);

//对读到的每一条kafka消息做处理

while(!signalHandler.beKilling && kc.hasNext()){

byte[] data = kc.getNext();

//转为String类型

String res=new String(data);

//消息处理逻辑

ProcessData d =new ProcessData();

d.processingMessage(res);

}

System.out.println("bye!");

}

@Override

publicvoid handle(Signal arg0){

// TODO Auto-generated method stub

beKilling =true;

}

}

说明:

(1)需要引用sun.misc的两个类:Signal和SignalHandler;

(2)添加一个变量bKilling用于标识该进程是否正在被杀,如果是,则跳出循环不在接收Kafka消息;

(3)一般接收“kill -15”的信号。

在eclipse开发环境中,引用sun.misc会报找不到类问题,其实该包在rt.jar包中。需要配置一下IDE,忽略掉Signal相关的错误和警告,如下图所示:

541e8900cbe25eb592b9db17ac601c57.png

如果尝试响应其他kill信号,运行程序时会报如下错误:

[user@data2 test]$ java -jar Test.jar

Exception in thread "main" java.lang.IllegalArgumentException: Signal already used by VM or OS: SIGKILL

at sun.misc.Signal.handle(Signal.java:166)

at TestSignal.main(TestSignal.java:12)

进程的启动与关闭

Java后台进程启动和关闭

启动:

[user@data2 test]$ nohup java -jar Test.jar &

查看日志:

[user@data2 test]$ more nohup.out

running ......

running ......

查看进程:

[user@data2 test]$ ps -ef | grep Test.jar

unicom 28005 27711 0 22:24 pts/0 00:00:00 java -jar Test.jar

unicom 28062 27711 0 22:24 pts/0 00:00:00 grep Test.jar

关闭进程:

[user@data2 test]$ kill -15 28005

查看日志:

[user@data2 test]$ more nohup.out

running ......

running ......

TERM is recevied.

running ......

[1]+ Done nohup java -jar Test.jar

附录

在以下场景中需要使用SignalHandler来响应kill信号:

(1)文件操作;

(2)数据库操作;

(3)网络连接;

(4)循环处理的消息、数据记录等。

来源:CU技术社区

End

全国大学生科技创新大赛征稿函

征稿内容

机械设计等设计作品,通信作品、工程作品、机电作品、电子作品、科技作品等,可以是与之相关的论文,也可以是作品说明,只要是设计、通信、工程、机电、电子、科技等相关都可以。

评选方式

组委会本着“公开、公正、公平”的原则进行评审,奖项为一、二、三等奖,凡获奖作品均颁发荣誉证书。

1、由专家组成评审小组,对参赛作品进行评审。

2、部分优秀作品将在网站上宣传和表彰。

组别设置

本比赛下设组别与作品类别相同,如机械设计作品,则组别为机械设计组;通信作品,则组别为通信组,以此设置。

稿件发送

参赛作品以电子文档形式发送,邮件发送至:zgdxskjcxds@sina.com。主题为“大学生科技创新大赛+作品+作者姓名”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值