Как ждать процесса, который выводит строку, соответствующую шаблону в Java? - PullRequest
0 голосов
/ 06 декабря 2018

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

Я использую BufferedReader, чтобы читать строку за строкой из Process.getOutputStream при сопоставлении каждой строки с шаблоном.Он работал нормально, когда есть совпадение или процесс прервался перед любым совпадением.Но когда процесс больше не выводит строку после заданного временного ограничения, блок BufferedReader.readLine() и чтение потока из Process.getOutputStream никогда не завершаются.

Вот мой код.

private static Timer setTimeout(Runnable runnable, long timeoutMillis) {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            runnable.run();
            timer.cancel();
        }
    }, timeoutMillis);
    return timer;
}

static CompletableFuture<Process> startProcessAndWaitForMatchedOutput(
        ProcessBuilder processBuilder, String pattern, long waitForMillis) {
    final CompletableFuture<Process> completableFuture = new CompletableFuture<>();

    final Process process;
    try {
        process = processBuilder.start();
    } catch (IOException ex) {
        completableFuture.completeExceptionally(ex);
        return completableFuture;
    }

    final Pattern compiledPattern = Pattern.compile(pattern);

    final Timer timeoutTimer = setTimeout(() -> 
        completableFuture.completeExceptionally(new WaitForTimeExceededException()),
        waitForMillis);

    new Thread(() -> {
        try (InputStream processOutputStream = process.getInputStream();
             InputStreamReader inputStreamReader = new InputStreamReader(processOutputStream);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {

            String line;
            /* The thread is blocked here. 
            Indeed the code call this method always return because 
            my completableFuture always completes. 
            But the problem is there is a running thread 
            which is a waste of resource. */
            while ((line = bufferedReader.readLine()) != null) {
                if (compiledPattern.matcher(line).matches()) {
                    completableFuture.complete(process);
                    timeoutTimer.cancel();
                    return;
                }
            }

            completableFuture.completeExceptionally(new OutputDidNotMatchException());
            timeoutTimer.cancel();
        } catch (IOException ex) {
            completableFuture.completeExceptionally(ex);
            timeoutTimer.cancel();
        }
    }).start();

    return completableFuture;
}

Правильно ли мое решение?Если нет, есть ли библиотеки, которые решают мою проблему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...