Многопроцессорность через Processbuilder Связь, остановка в readline () для BufferedReader ()

1

Я пытаюсь разрешить связь между одной программой (программа запуска, если хотите), и программами, которые запускаются через Processbuilder. Я работаю нормально, но вход, кажется, останавливается, когда он достигает метода readline() в helloworld (созданный процесс).

Ниже приведена 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!");


}

Получаемый результат:

Привет мир!

2 Пожалуйста, введите что-нибудь!

Это тестовый ввод

отправка ввода

Попытка разрешить ввод

Как вы можете видеть, я успешно завершаю цикл while (! Br.ready()), и я останавливаюсь на br.readLine();

Я знаю, что inheritIO() существует, но для этого случая я использую BufferedOuput для отправки команд, которые затем разбираются и отправляются в оператор switch, который, в свою очередь, вызывает соответствующую функцию. Это связано с тем, что из диспетчера процессов можно запускать несколько процессов, думать о том, как весело при приходе нескольких вызовов System.in, и ничто не определяет, для какого процесса он нужен! Кроме того, это позволяет мне вызвать любой тип функции, даже те, которые не связаны с println или input.

  • 1
    Избавьтесь от бессмысленного цикла отжима, вызывая ready(). Последующий . Вызов readLine() уже заблокирует, и в течение точно правильного промежутка времени, в отличие от этого цикла, который почти всегда будет сбрасываться.
  • 0
    Спасибо, сделаю. Это было только для того, чтобы доказать, что код действительно достиг этой точки.
Теги:
multithreading
processbuilder
bufferedreader
bufferedwriter

1 ответ

1
Лучший ответ

Я считаю, что проблема здесь заключается в следующем:

  1. BufferedReader.ready() возвращает true если есть доступные символы для чтения. Это не гарантирует, что между ними есть каретки. (docs)
  2. BufferedReader.readLine() ищет возврат каретки для завершения строки. Если он не найден, он блокируется.
  3. BufferedWriter.write() не записывает автоматически завершающий возврат каретки.

Чтобы проверить, действительно ли это проблема, замените эту строку в runCommand():

in.write(reader.nextLine());

с:

in.write(reader.nextLine() + "\n");
  • 0
    Я мог бы поклясться, что проверил это ... Это действительно было проблемой. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню