如何通过流程构建器在4-5秒后停止执行命令?

Gan*_*h S 5 java timeout process processbuilder

参考代码 :

ProcessBuilder ps4;
Process pr4 = null;

String batchFile3 = new File(path + "/src/example.sh");

ps4 = new ProcessBuilder(batchFile3.getAbsolutePath());

ps4.redirectErrorStream(true);
ps4.directory(new File(path + "/src/"));

pr4 = ps4.start();

BufferedReade readRun = new BufferedReader(new InputStreamReader(pr4.getInputStream()));



if(pr4.waitFor()==0)
{

}

 String line,stre;   

while ((line = readRun.readLine()) != null) {

     System.out.print("-----" + line);

     if (line != null) {

           stre += line;

    }

}
Run Code Online (Sandbox Code Playgroud)
  • 在这里我得到了stre字符串,它可能是错误或由我正在执行的批处理文件生成的输出.

  • 我想停止批处理文件的执行,如果需要花费4-5秒来执行批处理文件执行过程.

  • 同样在这种情况下,我应该能够返回程序来处理一个块,只有在处理批处理文件的这种延迟发生时,才会执行该块,否则不应该处理该块.

dim*_*414 13

据我了解,如果运行时间超过四或五秒,您希望停止子进程.这不能直接使用ProcessBuilder(您可以看到类中不存在相关方法),但是一旦子进程开始,您就可以轻松地实现此行为.

Process.waitFor()在示例代码中调用是有问题的,因为它将无限期地阻止当前线程 - 如果您的进程花费超过五秒钟.waitFor()将不会停止它.但是.waitFor()过载,其兄弟姐妹需要一个timeout说法.

public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException
Run Code Online (Sandbox Code Playgroud)

如果需要,使当前线程等待,直到此Process对象表示的子进程终止,或者指定的等待时间过去.

Process.destroy()如果花费的时间太长,您可以同时使用它来停止该过程.例如:

Process process = new ProcessBuilder(command, and, arguments)
    .redirectErrorStream(true)
    .directory(workingDir)
    .start();

process.waitFor(5, TimeUnit.SECONDS);
process.destroy();
process.waitFor(); // wait for the process to terminate
Run Code Online (Sandbox Code Playgroud)

这依赖于在Process.destroy()已经完成的子进程上调用时无操作的事实.在Java 9之前,没有记录这种行为,但在实践中始终如此.另一种方法是检查返回值.waitFor(),但这会引入TOCTTOU竞赛.

怎么样Process.destroyForcibly()?一般来说,你不应该调用这种方法(JDK可能更清楚的另一件事),但是如果一个进程真正挂起,它可能就变得必要了.理想情况下,您应该确保您的子流程表现良好,但如果您必须使用.destroyForcibly()这个,我建议您这样做:

// Option 2
process.waitFor(5, TimeUnit.SECONDS);  // let the process run for 5 seconds
process.destroy();                     // tell the process to stop
process.waitFor(10, TimeUnit.SECONDS); // give it a chance to stop
process.destroyForcibly();             // tell the OS to kill the process
process.waitFor();                     // the process is now dead
Run Code Online (Sandbox Code Playgroud)

这确保了行为不当的过程将被迅速杀死,同时仍然给予正确实施的程序在被指示时退出的时间.的确切行为.destroy().destroyForcibly()具体的操作系统,但在Linux上我们可以看到,它们对应于SIGTERMSIGKILL:

int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM;
kill(pid, sig);
Run Code Online (Sandbox Code Playgroud)

您应该很少需要打电话.destroyForcibly(),如果您发现有必要,我建议您只添加它.

选项2在概念上类似于使用如下timeout命令:

$ timeout --kill-after=10 5 your_command
Run Code Online (Sandbox Code Playgroud)

Process.waitFor(long, TimeUnit)在Java 7中复制很容易,默认的Java 8实现没有什么神奇之处:

public boolean waitFor(long timeout, TimeUnit unit)
    throws InterruptedException
{
    long startTime = System.nanoTime();
    long rem = unit.toNanos(timeout);

    do {
        try {
            exitValue();
            return true;
        } catch(IllegalThreadStateException ex) {
            if (rem > 0)
                Thread.sleep(
                    Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
        }
        rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
    } while (rem > 0);
    return false;
} 
Run Code Online (Sandbox Code Playgroud)