Я пишу 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);
Iзатем перейдите к запуску трех разных потоков, каждый из которых обрабатывает отдельный поток.У меня также есть три SynchronousQueues, которые обрабатывают ввод и вывод (один используется в качестве ввода для входного потока, один для информирования outputQueue о запуске новой команды и один для вывода).Например, поток входного потока выглядит следующим образом:
while (!killThreads) {
String input = inputQueue.take();
processInput.write(input.getBytes());
processInput.flush();
IOQueue.put(input);
}
Если я удаляю цикл while и просто выполняю его один раз, кажется, что все работает отлично.Очевидно, что если я попытаюсь выполнить его снова, PumpStreamHandler выдает исключение, потому что к нему обращались два разных потока.
Проблема здесь в том, что кажется, что processInput действительно не очищается, пока поток не завершится.При отладке приложение командной строки действительно получает свои входные данные только после завершения потока, но никогда не получает их, если цикл while сохраняется.Я пробовал много разных вещей, чтобы заставить ProcessInput сбрасываться, но, похоже, ничего не работает.
Кто-нибудь пробовал что-то подобное раньше?Есть ли что-то, что я пропускаю?Любая помощь будет принята с благодарностью!