Piszę aplikację Java, która musi korzystać z zewnętrznej aplikacji wiersza poleceń przy użyciu biblioteki Apache Commons Exec. Aplikacja, którą muszę uruchomić, ma dość długi czas ładowania, dlatego lepiej byłoby utrzymać jedną instancję przy życiu, zamiast tworzyć nowy proces za każdym razem. Sposób działania aplikacji jest bardzo prosty. Po uruchomieniu oczekuje na kilka nowych danych wejściowych i generuje dane jako dane wyjściowe, z których oba korzystają ze standardowego wejścia/wyjścia aplikacji.Kłopoty z wprowadzaniem wielu poleceń do polecenia za pomocą Apache Commons Exec i wypakowywanie wyjścia
Ideą byłoby wykonanie CommandLine, a następnie użycie PumpStreamHandler z trzema oddzielnymi strumieniami (wyjście, błąd i dane wejściowe) i wykorzystanie tych strumieni do interakcji z aplikacją. Do tej pory miałem tę pracę w podstawowych scenariuszach, w których mam jedno wejście, jedno wyjście, a następnie aplikacja wyłącza się. Ale gdy tylko próbuję przeprowadzić drugą transakcję, coś idzie nie tak.
Po stworzył mój CommandLine, tworzę Executor i uruchomić go tak:
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 następnie przystąpić do uruchomienia trzy różne tematy, każdy z jednym magazynowe inny strumień. Mam również trzy SynchronousQueues, które obsługują wejście i wyjście (jeden używany jako wejście dla strumienia wejściowego, jeden do poinformowania outputQueue, że nowe polecenie zostało uruchomione i jedno dla wyjścia). Na przykład, nić strumień wejściowy wygląda następująco:
while (!killThreads) {
String input = inputQueue.take();
processInput.write(input.getBytes());
processInput.flush();
IOQueue.put(input);
}
Jeśli usunąć pętli while i wykonać tylko ten jeden raz, wszystko wydaje się działać idealnie. Oczywiście, jeśli spróbuję wykonać to ponownie, PumpStreamHandler zgłasza wyjątek, ponieważ dostęp do niego miały dwa różne wątki.
Problem polega na tym, że wygląda na to, że processInput nie jest naprawdę przepłukiwany, dopóki wątek się nie skończy. Po debugowaniu aplikacja wiersza poleceń naprawdę otrzymuje swoje wejście dopiero po zakończeniu wątku, ale nigdy nie otrzyma go, jeśli pętla while będzie zachowana. Próbowałem wiele różnych rzeczy, aby proces processInput się spłukał, ale nic nie działa.
Czy ktoś wcześniej próbował czegoś podobnego? Czy jest coś, czego mi brakuje? Każda pomoc będzie bardzo ceniona!
powinieneś dodać tag java do swojego posta, do najbardziej doświadczonych "oczu" na temat twojego problemu. Powodzenia. – shellter