解决Runtime.getRuntime().exec长时间等待无法获取返回状态值

情景再现

test.py

#!/usr/bin/python
import time
import sys
 
print "Start : %s" % time.ctime()
time.sleep( 5 )
print "End : %s" % time.ctime()
for i in range(0, 1000000):
	sys.stderr.write("msg")

Test.java

import java.io.IOException;

/**
 * @author zhy
 * @date 2020/2/12 15:17
 */

public class Test {
    public static void main(String[] args) throws IOException {
            Process process = null;
            try {
                process = Runtime.getRuntime().exec("python test.py");
                process.waitFor();
                int i = process.exitValue();
                System.out.println(i);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}

1.先直接执行test.py

python test.py

可以看到程序正常结束了,错误信息也正常打印了

2.执行java代码,Test.java

//编译
javac Test.java
//执行
java Test

发现根本无法获取py文件执行成功返回的0

发现问题

Runtime.getRuntime()返回当前应用程序的Runtime对象,该对象的exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。通过Process可以控制该子进程的执行或获取该子进程的信息。
它的所有标准io(即stdin,stdout,stderr)操作都将通过三个流(getOutputStream(),getInputStream(),getErrorStream())重定向到父进程。父进程使用这些流来提供到子进程的输入和获得从子进程的输出。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流出现失败,则可能导致子进程阻塞,甚至产生死锁。(如果程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waifor()

process .getErrorStream():获得子进程的错误输出流
process .getInputStream():获得子进程的普通输出流

解决

修改java中的代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @author zhy
 * @date 2020/2/12 15:17
 */

public class Test {
    public static void main(String[] args) throws IOException, InterruptedException {
        Process p = Runtime.getRuntime().exec("python test.py");
        final InputStream is1 = p.getInputStream();
        new Thread(() -> {
            BufferedReader br = new BufferedReader(new InputStreamReader(is1));
            try{
                while(br.readLine() != null) ;
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }).start();
        InputStream is2 = p.getErrorStream();
        BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
        while(br2.readLine() != null){}
        int i = p.waitFor();
        System.out.println(i);
    }
}

 

`Runtime.getRuntime().exec()`是Java中用于执行外部进程的方法。它返回一个Process对象,可以使用这个对象控制和监视进程的执行。 语法如下: ```java public Process exec(String command) throws IOException ``` 其中,command是要执行命令。 例如,执行一个简单的命令: ```java Process process = Runtime.getRuntime().exec("ls"); ``` 这个代码将在当前目录下执行`ls`命令,并返回一个Process对象。 然而,这只是一个简单的例子。实际上,在执行外部进程时,还需要考虑很多其他方面,例如进程的输入、输出、错误处理等。 下面是一个更复杂的例子,演示如何使用`Runtime.getRuntime().exec()`执行一个Python脚本,并读取它的输出: ```java try { Process process = Runtime.getRuntime().exec("python myscript.py"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } ``` 在这个例子中,我们使用`BufferedReader`读取进程的输出,并将其打印到控制台上。如果进程执行时发生错误,我们可以使用`process.getErrorStream()`方法获取错误流,并对其进行处理。 需要注意的是,`Runtime.getRuntime().exec()`方法在执行外部进程时可能会阻塞当前线程,因此在处理输出时需要开启一个新的线程。此外,还需要注意处理输入、输出、错误流的顺序,以避免死锁等问题。 总之,`Runtime.getRuntime().exec()`是一个非常强大的方法,可以在Java中轻松地执行外部命令和脚本。但是,它需要仔细处理各种输入、输出、错误流,以确保进程能够正确执行
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值