1

我在 linux 中为 java 进程对象调用 exitValue() 时得到“0”值,但偶尔子线程(错误和输出流读取器)未完成并卡在 join 中。进程的 exitValue() 的“0”值不应该保证所有子进程都成功终止吗?

private class ReadStdoutThread extends Thread {
        private Process m_prc;
        private StringBuffer m_sb;

        public ReadStdoutThread(Process prc, StringBuffer sb) {
            m_prc = prc;
            m_sb = sb;
        }

        public void run() {
            BufferedReader stdout =
                new BufferedReader(new InputStreamReader(m_prc.getInputStream()));
            String line = null;
            try {
                while ((line = stdout.readLine()) != null) {
                    System.out.println("Stdout: " + line);
                    m_sb.append(line + "\n");
                }
                stdout.close();
            } catch (IOException e) {
                System.out.println(e.toString());
                return;
            }
        }
    }

    private class ReadStderrThread extends Thread {
        private Process m_prc;
        private StringBuffer m_sb;

        public ReadStderrThread(Process prc, StringBuffer sb) {
            m_prc = prc;
            m_sb = sb;
        }

        public void run() {
            BufferedReader stderr =
                new BufferedReader(new InputStreamReader(m_prc.getErrorStream()));
            String line = null;
            try {
                while ((line = stderr.readLine()) != null) {
                    System.out.println("Stderr: " + line);
                    m_sb.append(line + "\n");
                }
                stderr.close();
            } catch (IOException e) {
                System.out.println(e.toString());
                return;
            }
        }
    }

    public static String runCmd(String cmd, long timeoutMS) throws IOException,
                                                                   InterruptedException {
        Process prc = Runtime.getRuntime().exec(cmd);
        long startTimeMS = System.currentTimeMillis();
        boolean isRunning = true;
        System.out.println("Command has started.");
        StringBuffer sb = new StringBuffer();
        ReadStdoutThread ot = new HostCommand().new ReadStdoutThread(prc, sb);
        ReadStderrThread et = new HostCommand().new ReadStderrThread(prc, sb);
        ot.start();
        et.start();
        if (timeoutMS == 0) {
            System.out.println("Thread will wait until command is completed.");
            prc.waitFor();
        } else {
            System.out.println("Command timeout (ms): " + timeoutMS);
            synchronized (prc) {
                int n = -1;
                while (isRunning) {
                    prc.wait(1000);
                    try {
                        n = prc.exitValue();
                        System.out.println("Command has completed with value: " +
                                           n);
                        m_processExitValue = n;
                        isRunning = false;
                    } catch (IllegalThreadStateException e) {
                        // command is still running
                        isRunning = true;
                    }
                    if ((System.currentTimeMillis() - startTimeMS >
                         timeoutMS) && isRunning) {
                        System.out.println("Timeout has reached, and command is still running.  Command will be interrupted.");
                        prc.destroy();
                        m_processExitValue = n;
                        isRunning = false;
                    }
                }
            }
        }
        try {
            ot.join(timeoutMS);
        }
        catch(InterruptedException e) {
            throw e;
        }
        try {
            et.join(timeoutMS);
        }
        catch(InterruptedException e) {
            throw e;
        }
        return sb.toString();
    }
4

2 回答 2

0

根据文档,如果任何子进程尚未终止,则该方法应返回 IllegalThreadStateException,否则将返回 0,表示正常终止。

来源:https ://docs.oracle.com/javase/7/docs/api/java/lang/Process.html

于 2015-12-28T20:17:55.610 回答
0

不能保证 ReadStdoutThread 和 ReadStderrThread 已完成执行。waitForProcess 的API 与您为从 Process 读取标准输入和错误流而生成的两个单独线程之间没有同步。你需要使用 :ot.join();et.join();在调用之后ot.start();et.start();。基本上,应该在调用之前调用 joinProcess.waitFor()

于 2016-02-13T14:05:02.020 回答