Java IO 输入流在读取外部 C 程序的标准输出和标准错误时阻塞

标签 java java-io

我几天前在这里发布了同样的问题(Java reading standard output from an external program using inputstream),我发现了一些在阅读时处理阻塞的极好的建议(while(is.read()) != -1)) , 但我仍然无法解决问题。

看完这个类似问题的答案后,

Java InputStream blocking read (特别是 Guss 发布的答案),

我开始相信,如果程序是交互式的,那么使用 is.read() != -1 条件循环输入流是行不通的(也就是说,它需要来自用户的多个输入,并在后续输入时呈现额外的输出,并且只有在给出明确的退出命令时程序才会退出)。我承认我对多线程知之甚少,但我认为我需要的是一种机制,可以在需要用户输入时立即暂停输入流线程(stdout、stderr 各一个),并在输入完成后恢复提供以防止阻塞。以下是我当前的代码,它在指示的行上遇到了一个 block :

EGMProcess egm = new EGMProcess(new String[]{directory + "/egm", "-o",
                "CasinoA", "-v", "VendorA", "-s", "localhost:8080/gls/MessageRobot.action ",
                "-E", "glss_env_cert.pem", "-S", "glss_sig_cert.pem", "-C", "glsc_sig_cert.pem",
                "-d", "config", "-L", "config/log.txt", "-H", "GLSA-SampleHost"}, new String[]{"PATH=${PATH}"}, directory);

    egm.execute();

    BufferedReader stdout = new BufferedReader(new InputStreamReader(egm.getInputStream()));
    BufferedReader stderr = new BufferedReader(new InputStreamReader(egm.getErrorStream()));

    EGMStreamGobbler stdoutprocessor = new EGMStreamGobbler(stdout, egm);
    EGMStreamGobbler stderrprocessor = new EGMStreamGobbler(stderr, egm);

    BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(egm.getOutputStream()));


    stderrprocessor.run(); //<-- the block occurs here!
    stdoutprocessor.run();


    //EGM/Agent test cases


        //check bootstrap menu
        if(!checkSimpleResult("******** EGM Bootstrap Menu **********", egm))
        {
            String stdoutdump = egm.getStdOut();
            egm.cleanup();
            throw new Exception("can't find '******** EGM Bootstrap Menu **********'" +
                "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump);
        }

        //select bootstrap
        stdin.write("1".toCharArray());
        stdin.flush();

        if(!checkSimpleResult("Enter port to receive msgs pushed from server ('0' for no push support)", egm)){
            String stdoutdump = egm.getStdOut();
            egm.cleanup();
            throw new Exception("can't find 'Enter port to receive msgs pushed from server ('0' for no push support)'" +
                    "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump);
        }

...

<p> public class EGMStreamGobbler implements Runnable{</p> private BufferedReader instream; private EGMProcess egm; public EGMStreamGobbler(BufferedReader isr, EGMProcess aEGM) { instream = isr; egm = aEGM; } public void run() { try{ int c; while((c = instream.read()) != 1) { egm.processStdOutStream((char)c); } } catch(IOException e) { e.printStackTrace(); } }

}

对于代码的长度,我深表歉意,但我的问题是,

1) 有什么方法可以在不使用 read() 的情况下控制接收输入流(stdout、stderr)的过程?还是我只是执行得很糟糕?

2) 多线程是否是开发接收输入流和写入输出过程的正确策略?

PS:如果有人能提供类似问题的解决方案,那将对我有很大帮助!

最佳答案

代替

stderrprocessor.run(); //<-- the block occurs here!
stdoutprocessor.run();

您需要启动线程:

Thread errThread = new Thread(stderrprocessor);
errThread.setDaemon( true );
errThread.start();

Thread outThread = new Thread(stdoutprocessor);
outThread.setDaemon( true );
outThread.start();

run()只是Runnable中指定的一个方法。 Thread.start() 在新的 Thread 中调用 Runnable 上的 run()

关于Java IO 输入流在读取外部 C 程序的标准输出和标准错误时阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1105569/

相关文章:

java - 对于 ARM 开发,您建议使用哪种 Java 嵌入式 VM?

带有 HTTP 上传的 Java ProgressBar 不更新

java - 哪种方式更好地从 http 获取响应?为什么?

java - 如何在不覆盖第一行的情况下将相同的对象保存在数组列表中

java - 如何返回和删除文件?

java - 使用Java获取不同计算机上的资源

java - 如何修改StanfordNLP中的TokenRegex规则?

java - 如何获取并设置 "messaging provider"以便 JAXM 客户端调用异步 SOAP API?

java - 使用 for(boolean haveNext = false;;) 而不是 while(cond)

java - 如何将源代码发送给我的客户到应用程序?