您的位置:首页 > 编程语言 > Java开发

Java中Process类的使用与注意事项

2015-08-24 11:58 351 查看
(1)在项目开发中,经常会遇到调用其它程序功能的业务需求,在java中通常有两种实现方法

Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(cmd);


Process p=new ProcessBuilder(cmd).start();


(2)在这里就需要认识一下process类:process是一个抽象的类,它包含6个抽象的方法

abstract public OutputStream getOutputStream();

abstract public InputStream getInputStream();

abstract public InputStream getErrorStream();

abstract public int waitFor() throws InterruptedException;

abstract public int exitValue();

abstract public void destroy();


process类提供获取子进程的输入流、子进程的输出流、子进程的错误流、等待进程完成、检查进程的推出状态以及销毁进程的方法;在这里需要提及的是创建的子进程没有自己的控制台或终端,其所有的io操作都是通过(输入流、输出流、错误流)重定向到父进程中。

(3)来说说今天业务需求[waitfor()]:我需要在linux下首先将一个文件copy到指定的文件夹下面,之后需要将该文件夹下面的文件加入指定的jar中,那么问题就来了,必须保证其先后顺序,也就书说再执行第二个命令的时候第一个命令必须完成。

public void cmd(String cmd){
try {
Process ps= Runtime.getRuntime().exec(cmd);
} catch (Exception e) {
logger.info(e.getMessage(),e);
}
}


main函数如下:

public static void main(String[] args){
String copy="cp -rf "+source+" "+target;
String jar="jar -uvf "+jar+" "+file;
cmd(copy);
cmd(jar);
}


但是结果是新生成的jar中压根没有新加入的文件,但是文件确实copy到了指定的文件夹中,也就是谁两个命令都执行了,问题的关键就是“异步”,这时候需要waitFor()的介入

public void cmd(String cmd){
try {
Process ps= Runtime.getRuntime().exec(cmd);
ps.waitFor();
} catch (Exception e) {
logger.info(e.getMessage(),e);
}
}


那么问题就解决了!

(4)前不久遇到一个奇怪的问题就是ajax调用没有返回值,我在service中实现了process的调用。

String[] commands = { commandGenerate,commandPublish};
PrintWriter printWriter = response.getWriter();
for (String comm : commands) {
Runtime runtime = Runtime.getRuntime();
try {
logger.info("command is :{}",comm);
Process process = runtime.exec(comm, null, null);
BufferedInputStream inputStream = new BufferedInputStream(
process.getInputStream());
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));
String line;
while (bufferedReader.read() != -1) {
line = bufferedReader.readLine();
System.out.println(line);
}
bufferedReader.close();
inputStream.close();
printWriter.println("success");
} catch (IOException e) {
logger.error(e.getMessage(), e);
printWriter.println(e.getMessage());
}
}
printWriter.flush();
printWriter.close();


对应的controller为:

State state = new State();
String message="";
try {
message = missionService.syntax(taskName, response);
} catch (InterruptedException e) {
e.printStackTrace();
}
state.setSuccess(true);
state.setMessage(message.trim());
return state;


打印state.getMessage()确实可以获得值,但是state返回就是空,刚开始以为是ajax的timeout时间的问题:修改了ajax的timeout时间仍然不行;将message直接赋值,然thread等待20s,结果是可以返回的,所以问题最终定为于service的这段实现。

原因分析:在上面提及了,process创建的子进程没有自己的控制台或终端,其所有的io操作都是通过(输入流、输出流、错误流)重定向到父进程中,如果该可执行程序的输入、输出或者错误输出比较多的话,而由于运行窗口的标准输入、输出等缓冲区有大小的限制,则可能导致子进程阻塞,甚至产生死锁,其解决方法就是在waitfor()方法之前读出窗口的标准输出、输出、错误缓冲区中的内容。

for (String comm : commands) {
logger.info("the comm time is:"+new Date().getTime()+" the comm is:"+comm);
Runtime runtime = Runtime.getRuntime();
Process p=null;
try {
p = runtime.exec(comm ,null,null);
final InputStream is1 = p.getInputStream();
final InputStream is2 = p.getErrorStream();
new Thread() {
public void run() {
BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
try {
String line1 = null;
while ((line1 = br1.readLine()) != null) {
if (line1 != null){
logger.info("p.getInputStream:"+line1);
if(line1.indexOf("syntax check result:")!=-1){
builder.append(line1);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
is1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();

new Thread() {
public void  run() {
BufferedReader br2 = new  BufferedReader(new  InputStreamReader(is2));
try {
String line2 = null ;
while ((line2 = br2.readLine()) !=  null ) {
if (line2 != null){
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
is2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
p.waitFor();
p.destroy();
} catch (Exception e) {
try{
p.getErrorStream().close();
p.getInputStream().close();
p.getOutputStream().close();
}
catch(Exception ee){}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: