zoukankan      html  css  js  c++  java
  • 用Runtime.getRuntime().exec()需要注意的地方

    有时候我们可能需要调用系统外部的某个程序,此时就可以用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序。

    此方法返回一个java.lang.Process对象,该对象可以得到之前开启的进程的运行结果,还可以操作进程的输入输出流。

    Process对象有以下几个方法:

      1、destroy()      杀死这个子进程

      2、exitValue()      得到进程运行结束后的返回状态

      3、waitFor()       得到进程运行结束后的返回状态,如果进程未运行完毕则等待知道执行完毕

      4、getInputStream()  得到进程的标准输出信息流

      5、getErrorStream()  得到进程的错误输出信息流

      6、getOutputStream() 得到进程的输入流

    现在来讲讲exitValue(),当线程没有执行完毕时调用此方法会跑出IllegalThreadStateException异常,最直接的解决方法就是用waitFor()方法代替。

    但是waitFor()方法也有很明显的弊端,因为java程序给进程的输出流分配的缓冲区是很小的,有时候当进程输出信息很大的时候回导致缓冲区被填满,如果不及时处理程序会阻塞。如果程序没有对进程的输出流处理的会就会导致执行exec()的线程永远阻塞,进程也不会执行下去直到输出流被处理或者java程序结束。

    解决的方法就是处理缓冲区中的信息,开两个线程分别去处理标准输出流和错误输出流。

    程序如下:

    复制代码
    public class ExecTest {
        
        public static void main(String[] args) throws IOException, InterruptedException {
          String cmd = "cmd /c dir c:\windows";
          final Process process = Runtime.getRuntime().exec(cmd);
          printMessage(process.getInputStream());
          printMessage(process.getErrorStream());
          int value = process.waitFor();
          System.out.println(value);
        }
        
        private static void printMessage(final InputStream input) {
          new Thread(new Runnable() {
             public void run() {
                Reader reader = new InputStreamReader(input);
                BufferedReader bf = new BufferedReader(reader);
                String line = null;
                 try {
                    while((line=bf.readLine())!=null) {
                        System.out.println(line);
                    }
                 } catch (IOException e) {
                    e.printStackTrace();
                 }
             }
          }).start();
        }
    }
    复制代码

    如上程序,读取进程的输出信息并打印到控制台就不会发生阻塞,程序能正常的结束。

    tips:

      cmd命令不能需要加上cmd /c才能执行,不然java会去path中找dir.exe

      在windows一般字符集编码为GBK,需要在转换成Reader的时候指定为GBK编码.

  • 相关阅读:
    GET请求和POST请求的本质区别
    go切片的Add与Del
    滚动到指定位置的问题
    promise---批量调用接口,等待所有的请求发完
    this argument
    html2canvas截图 下载图片
    数组合并去重
    vue项目踩坑
    关于java中的栈和堆
    用python实现一个最简单版本的mysql数据库连接池
  • 原文地址:https://www.cnblogs.com/fclbky/p/6112180.html
Copyright © 2011-2022 走看看