多进程通过processbuilder通信,冻结在readline() for BufferedReader()

Multiprocess via processbuilder Communication, freeze at readline() for BufferedReader()

我试图允许一个程序(程序启动器,如果你愿意的话)和它通过 processbuilder 启动的程序之间进行通信。我的输出工作正常,但输入似乎在到达 helloworld(创建的进程)中的 readline() 方法时停止。

下面是helloworld.java:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;


public class helloworld {
public static void main (String[] args) {
System.out.println ("println(\"Hello World!\")");
System.out.println ("getInput()");
Scanner in = new Scanner(System.in);
BufferedReader br = new BufferedReader(
        new InputStreamReader(System.in));
String input = "";
try {
    // wait until we have data to complete a readLine()
    while (!br.ready()) {
      Thread.sleep(200);
    }
    System.out.println("println(\"Attempting to resolve input\")");
    input = br.readLine();  

^这是程序挂起的地方^

    if(input != null){
        System.out.println("println(\"This should appear\")");
    }
    System.out.println("println(\"input recieved " + input + "\")");
} catch (InterruptedException | IOException e) {
    System.out.println("ConsoleInputReadTask() cancelled");
  }

System.out.println("println(\"You said: " + input + "\")");
//System.out.println("println(\"You said: " + in. + "!\")");

in.close();
System.exit(0);
}
}

这是接收其他进程的输出 (println) 的地方:

public void run() {
    try {
        //cfile = files[indexval].getAbsolutePath();
        String[] commands = 
            {
                "java", //Calling a java program
                "-cp" , //Denoting class path
                cfile.substring(0,cfile.lastIndexOf(File.separator) ), //File path
                program}; //Class name

        ProcessBuilder probuilder = new ProcessBuilder( commands );

        //start the process
        Process process = probuilder.start();

        //Read out dir output
        //probuilder.inheritIO(); //Can inherit all IO calls
        InputStream is = process.getInputStream();
        OutputStream os = process.getOutputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        BufferedReader br = new BufferedReader(isr);
        String line;
        /*System.out.printf("Output of running %s is:\n",
                Arrays.toString(commands));*/
        while ((line = br.readLine()) != null) {
            myController.runCommand(line, "Please enter something!", bw);
            //System.out.println(line);
        }
        br.close();
        os.close();
        } catch (IOException e){
            e.printStackTrace();
        }
    System.out.println("programclosed");
}

这是它调用的函数:

public synchronized void runCommand(String line, Object... arguments) throws     IOException {
    String[] tokens;
    if(line.contains("(")){
        tokens = line.split("\(",2);

    switch(tokens[0]){
    case "println": //Println - format println(String strng)
        tokens[1] = tokens[1].substring(1, tokens[1].length() - 2);
        System.out.println(tokens[1]);
        break;
    case "getInput": //Get input - format getInput(String command, String message, BufferedWriter br)
        Scanner reader = new Scanner(System.in);
        System.out.println(arguments.length);
        System.out.println(((String)arguments[0]));
        BufferedWriter in = ((BufferedWriter)arguments[1]);
        in.write(reader.nextLine());
        System.out.println("sending input");
        in.flush();
        reader.close();
        break;
    default:
        System.out.println("Invalid command recieved!");
    }
    } else
        System.out.println("Invalid command recieved!");


}

我收到的输出是:

Hello World!

2 Please enter something!

This is a test input

sending input

Attempting to resolve input

如您所见,我成功退出了 while(!br.ready()) 循环,并在 br.readLine();

处停止

我知道 inheritIO() 存在,但对于这种情况,我使用 BufferedOuput 发送命令,然后解析这些命令并将其发送到 switch 语句,后者又调用相应的函数。这是因为可以从进程管理器启动多个进程,想想当多个 System.in 调用到达时的乐趣,没有什么可以确定它是哪个进程!此外,这允许我调用任何类型的函数,甚至是那些与 println 或输入无关的函数。

我认为这里的问题是由以下原因造成的:

  1. BufferedReader.ready() returns true 如果有任何字符可供读取。不保证其中有回车return。 (docs)
  2. BufferedReader.readLine() 寻找回车 return 来完成一行。如果找不到,它会阻止。
  3. BufferedWriter.write() 不会自动写入终止回车 return.

要测试这是否真的是问题所在,请将 runCommand() 中的这一行替换为:

in.write(reader.nextLine());

与:

in.write(reader.nextLine() + "\n");