书是人类进步的阶梯,尤其是烧掉的那些。 ——连岳
游客 登录

为Process.waitFor设置超时

Java中在使用Runtime.getRuntime().exec(command)调用系统命令后,一般会调用Process.waitFor()来等待命令执行结束,获取执行结果。今天一个悲剧的事实证明了,即使只是调用了很简单的脚本命令,在调用Process.waitFor()后同样可能发生无休止或者接近于无休止的阻塞。处理完故障之后痛定思痛,决定在代码中加入超时控制,但是Process.waitFor()本身并不支持超时时间设置。一个方法是改用非阻塞的Process.exitValue()方法,然后轮询检查进程状态,这种方式比较消耗CPU,以至于轮询间隔也不能设置得太小,总归不是很完美。另外就是多起一个线程,借助于其他的超时机制来控制。最后使用的代码如下:

public class ProcessUtils {
   
    /**
     * 运行一个外部命令,返回状态.若超过指定的超时时间,抛出TimeoutException
     * @param command
     * @param timeout
     * @return
     * @throws IOException
     * @throws InterruptedException
     * @throws TimeoutException
     */
    public static int executeCommand(final String command, final long timeout) throws IOException, InterruptedException, TimeoutException {
        Process process = Runtime.getRuntime().exec(command);
        Worker worker = new Worker(process);
        worker.start();
        try {
            worker.join(timeout);
            if (worker.exit != null){
                return worker.exit;
            } else{
                throw new TimeoutException();
            }
        } catch (InterruptedException ex) {
            worker.interrupt();
            Thread.currentThread().interrupt();
            throw ex;
        } finally {
            process.destroy();
        }
    }
   

    private static class Worker extends Thread {
        private final Process process;
        private Integer exit;

        private Worker(Process process) {
            this.process = process;
        }

        public void run() {
            try {
                exit = process.waitFor();
            } catch (InterruptedException ignore) {
                return;
            }
        }
    }

}
分享到:
你现在以游客身份发表评论(使用gmail账户登录):

电子邮箱(必填,邮箱地址将不会公开)

(必填)

(快捷键 Ctrl+Enter)