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

4 java java-io

我几天前在这里发布了同样的问题(Java使用输入流读取外部程序的标准输出),我在阅读时遇到了一些块的优点(while(is.read())!= -1)),但我仍然无法解决问题.

在阅读了这个类似问题的答案后,

Java InputStream阻塞读取 (尤其是Guss发布的答案),

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

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);
        }
Run Code Online (Sandbox Code Playgroud)

...

public class EGMStreamGobbler implements Runnable{

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)有没有办法控制输入流(stdout,stderr)的过程而不使用read()?或者我只是执行这个很糟糕?

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

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

Cli*_*int 8

代替

stderrprocessor.run(); //<-- the block occurs here!
stdoutprocessor.run();
Run Code Online (Sandbox Code Playgroud)

你需要启动线程:

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

Thread outThread = new Thread(stdoutprocessor);
outThread.setDaemon( true );
outThread.start();
Run Code Online (Sandbox Code Playgroud)

run()只是一个指定的方法Runnable. Thread.start()呼吁run()Runnable一个新的Thread.