我需要在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方法的第一行),而计时器将在5秒后销毁该命令。
以下是我的代码的输出:
starting...0
started...0
done...5000
result : 1
Really Done...5000
BUILD SUCCESSFUL (total time: 25 seconds)正如您在输出中看到的,最后一行(“真正完成...”)在5秒内执行,但应用程序在25秒后结束。
我的问题是:即使我在计时器中调用了destroy方法,为什么jvm仍然等待进程完成?
发布于 2011-03-01 07:06:16
它是Windows上Java的Process.destroy()实现中的一个bug。问题是批处理脚本(或它的执行shell)会被终止,但不会终止它自己的子进程(这里的ping )。因此,ping仍然在.destroy()之后运行,也在.waitFor()之后运行。但不知何故,VM仍在等待ping完成,然后才会自行完成。
在Java端,似乎没有什么可以真正可靠地终止ping。
您可以考虑使用start (在您的批处理脚本中或外部)将ping作为一个单独的进程来调用。
(另请参阅此previous discussion。)
或者改为类unix的操作系统。
发布于 2014-03-04 00:25:51
如果您使用Unix/Linux,那么编写一个包装器bash shell脚本,以便在超时时中断外部命令,然后从Java调用包装器。
包装器脚本如下所示
#!/bin/bash
timeout 60 <your command>您可以通过检查脚本退出代码来检测是否超时,如果超时,则退出代码为124
看见
手册超时
发布于 2011-02-28 15:17:09
我可能是计时器的cancel方法有问题。尝试将计时器作为守护程序线程启动。
Timer t = new Timer(true);https://stackoverflow.com/questions/5138946
复制相似问题