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

网友投稿 253 2022-11-15

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

目录Process类的使用与注意事项说明1、在项目开发中2、在这里就需要认识一下process类3、来说说今天业务需求[waitfor()]:4、前不久遇到一个奇怪的问题就是ajax调用没有返回值java的process实例讲解

Process类的使用与注意事项说明

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.geKvJAiCatMessage(),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){}

}

}

java的process实例讲解

package cn.itcast.process;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

public class ProcessTest implements Runnable{

private Process process = null;

public ProcessTest() {

try {

process = Runtime.getRuntime().exec("java MyTest");

new Thread(this).start();

} catch (IOException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

ProcessTest processTest = new ProcessTest();

processTest.send();

}

public void send()

{

OutputStream outputStream = process.getOutputStream();

while(true)

{

try {

outputStream.write("this is good\r\n".getBytes());

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

public void run() {

InputStream inputStream = process.getInputStream();

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

String str = null;

try {

while(true)

{

str = bufferedReader.readLine();

System.out.println(str);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

理解下面这句话就能更加容易的理解上面的代码

在java程序中可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不在连接到键盘和显示器,而是以管道流的形式连接到父进程的 一个输出流和输入流对象上-好好理解这句代码就能看懂那个程序。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java——>字符型文件流,文件的常用操作方法
下一篇:一个关于debug的问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~