Проблема с предоставлением множественного ввода для команды с использованием Apache Commons Exec и извлечением вывода

Я пишу приложение Java, которое должно использовать внешнее приложение командной строки с использованием библиотеки Apache Commons Exec. Приложение, которое мне нужно запустить, имеет довольно длительное время загрузки, поэтому было бы предпочтительнее поддерживать один экземпляр в рабочем состоянии, а не каждый раз создавать новый процесс. Принцип работы приложения очень прост. После запуска он ожидает нового ввода и генерирует некоторые данные в качестве вывода, оба из которых используют стандартный ввод-вывод приложения.

Таким образом, идея состоит в том, чтобы выполнить CommandLine, а затем использовать PumpStreamHandler с тремя отдельными потоки (вывод, ошибка и ввод) и использовать эти потоки для взаимодействия с приложением. До сих пор у меня была эта работа в базовых сценариях, когда у меня есть один вход, один выход, а затем приложение закрывается.Но как только я пытаюсь провести вторую транзакцию, что-то идет не так.

После создания моей CommandLine я создаю свой Executor и запускаю его следующим образом:

this.executor = new DefaultExecutor();

PipedOutputStream stdout = new PipedOutputStream();
PipedOutputStream stderr = new PipedOutputStream();
PipedInputStream stdin = new PipedInputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(stdout, stderr, stdin);

this.executor.setStreamHandler(streamHandler);

this.processOutput = new BufferedInputStream(new PipedInputStream(stdout));
this.processError = new BufferedInputStream(new PipedInputStream(stderr));
this.processInput = new BufferedOutputStream(new PipedOutputStream(stdin));

this.resultHandler = new DefaultExecuteResultHandler();
this.executor.execute(cmdLine, resultHandler);

Затем я перехожу к запуску трех разных потоков, каждый одного, обрабатывающего другой поток. У меня также есть три SynchronousQueue, которые обрабатывают ввод и вывод (один используется как ввод для входного потока, один для информирования outputQueue о запуске новой команды и один для вывода). Например, поток входного потока выглядит так:

while (!killThreads) {
    String input = inputQueue.take();

    processInput.write(input.getBytes());
    processInput.flush();

    IOQueue.put(input);
}

Если я удалю цикл while и выполню его только один раз, все будет работать отлично. Очевидно, что если я попытаюсь выполнить его снова, PumpStreamHandler выдаст исключение, потому что к нему обратились два разных потока.

Проблема здесь в том, что кажется, что processInput действительно не сбрасывается до завершения потока. При отладке приложение командной строки действительно получает ввод только после завершения потока, но никогда не получает его, если цикл while сохраняется. Я пробовал много разных вещей, чтобы очистить processInput, но, похоже, ничего не работает.

Кто-нибудь пробовал что-то подобное раньше? Что мне не хватает? Любая помощь будет принята с благодарностью!

8
задан Thomas Berger 19 August 2011 в 17:47
поделиться