【问题标题】:Process Builder and Process in Java - how to execute a process with a timeout :? [duplicate]Java中的流程构建器和流程 - 如何执行超时流程:? [复制]
【发布时间】:2011-02-28 06:39:46
【问题描述】:

我需要在 java 中执行一个具有特定超时的外部批处理文件。这意味着如果批处理执行时间超过指定的超时时间,我需要取消执行。

这是我编写的示例代码:

public static void main(String[] args) throws IOException, InterruptedException {
    ProcessBuilder p = new ProcessBuilder("c:\\wait.bat", "25");  // batch file execution will take 25 seconds.
    final long l = System.currentTimeMillis();
    System.out.println("starting..." + (System.currentTimeMillis() - l));
    final Process command = p.start();
    System.out.println("started..." + (System.currentTimeMillis() - l));

    Timer t = new Timer();
    t.schedule(new TimerTask() {

        @Override
        public void run() {
            command.destroy();
        }
    }, 5000);   // it will kill the process after 5 seconds (if it's not finished yet).
    int i = command.waitFor();
    t.cancel();
    System.out.println("done..." + (System.currentTimeMillis() - l));
    System.out.println("result : " + i);

    System.out.println("Really Done..." + (System.currentTimeMillis() - l));
}

批处理文件“wait.bat”是这样的:

@echo off
echo starting the process...
@ping 127.0.0.1 -n 2 -w 1000 > nul
@ping 127.0.0.1 -n %1% -w 1000> nul
echo process finished succesfully
@echo on

正如您在代码中看到的,批处理文件需要 25 秒才能完成(main 方法中的第一行),Timer 将在 5 秒后销毁命令。

这是我的代码的输出:

starting...0
started...0
done...5000
result : 1
Really Done...5000
BUILD SUCCESSFUL (total time: 25 seconds)

正如您在输出中看到的,最后一行(“Really Done...”)在第 5 秒内执行,但应用程序在 25 秒后完成。

我的问题是:即使我在计时器中调用了 destroy 方法,为什么 jvm 仍在等待进程完成?

【问题讨论】:

  • 这个“BUILD SUCCESSFUL”在哪里出现
  • @Suraj :它的 netbeans 默认消息将在应用程序终止后显示。
  • 我知道这是一个相当古老的对话,但 process.destroy() 适用于 JDK 1.7.0_51。

标签: java process


【解决方案1】:

它是 Java 在 Windows 上的 Process.destroy() 实现中的 bug。问题是批处理脚本(或其执行shell)被杀死,但没有杀死它自己的子进程(这里的ping)。因此,ping 仍在.destroy().waitFor() 之后运行。但不知何故,VM 仍然在等待 ping 完成后再自行完成。

您似乎无法从 Java 端执行任何操作来真正可靠地终止 ping。

您可能会考虑使用start(在您的批处理脚本中或外部)将您的 ping 作为一个单独的进程来调用。

(另见previous discussion。)

或者换成类似unix的操作系统。

【讨论】:

    【解决方案2】:

    如果您使用 Unix/Linux,则编写一个包装器 bash shell 脚本以通过超时中断外部命令,然后从 Java 调用包装器。

    包装脚本看起来像

    #!/bin/bash
    timeout 60 <your command>
    

    您可以通过检查脚本退出代码来检测超时是否过期

    人工超时

    【讨论】:

      【解决方案3】:

      我可能是定时器的取消方法有问题。尝试将计时器作为守护线程启动。

      Timer t = new Timer(true);
      

      【讨论】:

      • 不,不是这个原因,还是一样的结果。
      • 当你想杀死它时尝试发送 CTRL+C 作为进程参数
      猜你喜欢
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多