zoukankan      html  css  js  c++  java
  • java调用第三方命令,process.waitfor()挂起(你不知道的坑)

    我们常在java中运行第三方程序,如sh、python,java提供一个Runtime.exec()方法,生成一个Process对象。今天在使用这个方法的时候,发现接口半天没有返回数据。查了一下,原来还有这样的一个坑。记录一下

    代码是网上的,见如下。

     public static String execCmd(String cmd, File dir) throws Exception {
            StringBuilder result = new StringBuilder();
    
            Process process = null;
            BufferedReader bufrIn = null;
            BufferedReader bufrError = null;
    
            try {
                // 执行命令, 返回一个子进程对象(命令在子进程中执行)
                process = Runtime.getRuntime().exec(cmd, null, dir);
    
                // 方法阻塞, 等待命令执行完成(成功会返回0)
                process.waitFor();
    
                // 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出(PS: 子进程的输出就是主进程的输入)
                bufrIn = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
                bufrError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
    
                // 读取输出
                String line = null;
                while ((line = bufrIn.readLine()) != null) {
                    result.append(line).append('
    ');
                }
                while ((line = bufrError.readLine()) != null) {
                    result.append(line).append('
    ');
                }
        return result
    }

    执行后,一直没有输出。原因如下:

    1. 主进程中调用Runtime.exec会创建一个子进程,用于执行shell脚本。子进程创建后会和主进程分别独立运行。

    2. 因为主进程需要等待脚本执行完成,然后对脚本返回值或输出进行处理,所以这里主进程调用Process.waitfor等待子进程完成。

    3. 通过shell脚本可以看出:子进程执行过程就是不断的打印信息。主进程中可以通过Process.getInputStream和Process.getErrorStream获取并处理。

    4. 这时候子进程不断向主进程发生数据,而主进程调用Process.waitfor后已挂起。当前子进程和主进程之间的缓冲区塞满后,子进程不能继续写数据,然后也会挂起。

    5. 这样子进程等待主进程读取数据,主进程等待子进程结束,两个进程相互等待,最终导致死锁

    解决方案:

        开两个线程在waitfor()命令之前读出窗口的标准输出缓冲区和标准错误流的内容。

            new Thread() {
                @Override
                public void run() {
                    BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    String line = null;
    
                    try {
                        while ((line = in.readLine()) != null) {
                            log.info("datax执行的结果为: "+line);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
    
            new Thread(){
                @Override
                public void run()
                {
                    BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                    String line = null;
                    StringBuilder result=new StringBuilder();
                    try
                    {
                        while((line = err.readLine()) != null)
                        {
                            result.append(line);
                        }
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                    finally
                    {
                        try
                        {
                            err.close();
                        }
                        catch (IOException e)
                        {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
  • 相关阅读:
    JavaScript操作符instanceof揭秘
    Linux打开txt文件乱码的解决方法
    Working copy locked run svn cleanup not work
    poj 2299 UltraQuickSort 归并排序求解逆序对
    poj 2312 Battle City 优先队列+bfs 或 记忆化广搜
    poj2352 stars 树状数组
    poj 2286 The Rotation Game 迭代加深
    hdu 1800 Flying to the Mars
    poj 3038 Children of the Candy Corn bfs dfs
    hdu 1983 Kaitou Kid The Phantom Thief (2) DFS + BFS
  • 原文地址:https://www.cnblogs.com/SunHuaJ/p/11065426.html
Copyright © 2011-2022 走看看