【问题标题】:Java Process execute for n seconds and print the outputJava 进程执行 n 秒并打印输出
【发布时间】:2019-08-20 11:53:30
【问题描述】:

我有一个 python 脚本,它下载一个文本文件,逐行读取它并将读取的行发送到 java。我需要将此操作限制为 5 秒,并接收 python 读取的任何内容。

为了测试一切是否正常,我尝试了这个:

import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

class ProcessTest {
    public static void main(String args[]) {
        try {
            File file = new File("/home/local/seconds.py");
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String testCase = "", temp = "";
            while ((temp = reader.readLine()) != null) {
                testCase = testCase.concat(temp + '\n');
            }
            reader.close();
            ProcessBuilder pb = new ProcessBuilder("python", "-c", testCase);
            Process p = pb.start();
            if (!p.waitFor(5, TimeUnit.SECONDS)) {
                reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((temp = reader.readLine()) != null) {
                    System.out.println(temp);
                }
                p.destroy();
                System.out.println("not ended");
            } else {
                System.out.println("ended");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

seconds.py 文件

from time import sleep
for i in range(1,11):
    print(i)
    sleep(1)

预期结果: 由于我已将进程 waitFor 的值指定为 5 秒,因此代码最多只能打印 5 秒。

得到的结果: 代码执行超过 5 秒,最多打印 10 秒。

如何设置进程的超时时间并打印缓冲区中的内容?

【问题讨论】:

  • 我试过没有 p.wait()。代码仍然打印到 10。
  • 另外,reader.readLine() 可能在连接终止之前不会返回,在这种情况下,它可能会抛出 IOException。这个answer 可能会对你有所帮助。
  • 我忘了说:waitFor(5, Timeout.Seconds) 不保证 5 秒的等待时间,您需要在处理 Inputsteam 时处理这个问题。使用 answer 中的 readInputStreamWithTimeout 应该可以为您做到这一点。

标签: java python process processbuilder


【解决方案1】:

waitFor 不适合这种情况。

waitFor 不会改变进程产生的输出量。无论您等待多长时间,您的循环都会消耗该过程可以产生的每一行输出。

就此而言,在大多数系统上,如果进程的输出没有被定期消耗,则进程可能会挂起,因此waitFor 在与打印输出的进程一起使用时可能不会按预期运行。

正如其他人指出的那样,p.wait(); 在这里不正确。该方法与流程无关;是继承的Object.wait方法,用于多线程之间的协作。

最简单的方法是简单地检查经过的时间:

Process p = pb.start();
long startTime = System.currentTimeMillis();
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((temp = reader.readLine()) != null) {
    long time = System.currentTimeMillis();
    if ((time - startTime) >= 5000) {
        p.destroy();
        System.out.println("not ended");
    }
    System.out.println(temp);
}
if (temp == null) {
    System.out.println("ended");
}
reader.close();

【讨论】:

  • readLine() 仍然会阻塞,因此在某种情况下 - 当没有可用的新输入时 - 它会停在那里直到 nextLine 到达(或抛出 IOException)。我不仅想从链接的答案中复制解决方案,还可以自己将其集成到您的答案中。
  • @second 你是对的,但这似乎是一个简单的案例,我怀疑高精度不是目标。为了精确,我很确定需要一个可中断的 Channel 以及一个额外的线程(实际上,其他问题中的一些答案确实推荐)。但这似乎超出了这里的范围。
  • 有时,当我阅读一些答案时,我觉得无论如何都知道答案的人只是假设某些事情,但对于那些不知道的人,不要明确提及它们。 -- 无论如何,虽然p.waitFor 可能不适合 5 秒的时间限制,但它适合有一个fallback,以防进程在给定时间内没有产生输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-24
相关资源
最近更新 更多