java本机进程超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1247390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 07:25:16  来源:igfitidea点击:

java native Process timeout

javaprocess

提问by deltanovember

At the moment I execute a native process using the following:

目前,我使用以下命令执行本机进程:

java.lang.Process process = Runtime.getRuntime().exec(command); 
int returnCode = process.waitFor();

Suppose instead of waiting for the program to return I wish to terminate if a certain amount of time has elapsed. How do I do this?

假设我不想等待程序返回,而是希望在经过一定时间后终止。我该怎么做呢?

采纳答案by Rich Seller

This is how the Plexus CommandlineUtils does it:

这是 Plexus CommandlineUtils 的工作方式:

Process p;

p = cl.execute();

...

if ( timeoutInSeconds <= 0 )
{
    returnValue = p.waitFor();
}
else
{
    long now = System.currentTimeMillis();
    long timeoutInMillis = 1000L * timeoutInSeconds;
    long finish = now + timeoutInMillis;
    while ( isAlive( p ) && ( System.currentTimeMillis() < finish ) )
    {
        Thread.sleep( 10 );
    }
    if ( isAlive( p ) )
    {
        throw new InterruptedException( "Process timeout out after " + timeoutInSeconds + " seconds" );
    }
    returnValue = p.exitValue();
}

public static boolean isAlive( Process p ) {
    try
    {
        p.exitValue();
        return false;
    } catch (IllegalThreadStateException e) {
        return true;
    }
}

回答by nos

You'd need a 2. thread that interrupts the thread that calls .waitFor(); Some non trivial synchronization will be needed to make it robust, but the basics are:

你需要一个 2. 中断调用 .waitFor() 的线程的线程;需要一些重要的同步才能使其健壮,但基础知识是:

TimeoutThread:

超时线程:

 Thread.sleep(timeout);
 processThread.interrupt();

ProcessThread:

进程线程:

  try {
      proc.waitFor(); 
    } catch (InterruptedException e) {
       proc.destroy();
    }

回答by ZZ Coder

All other responses are correct but it can be made more robust and efficient using FutureTask.

所有其他响应都是正确的,但可以使用 FutureTask 使其更加健壮和高效。

For example,

例如,

private static final ExecutorService THREAD_POOL 
    = Executors.newCachedThreadPool();

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit)
    throws InterruptedException, ExecutionException, TimeoutException
{
    FutureTask<T> task = new FutureTask<T>(c);
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}

final java.lang.Process[] process = new Process[1];
try {
    int returnCode = timedCall(new Callable<Integer>() {
        public Integer call() throws Exception {
            process[0] = Runtime.getRuntime().exec(command); 
            return process[0].waitFor();
        }
    }, timeout, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    process[0].destroy();
    // Handle timeout here
}

If you do this repeatedly, the thread pool is more efficient because it caches the threads.

如果重复执行此操作,线程池会更高效,因为它会缓存线程。

回答by mickthompson

What about the Groovyway

Groovy方式怎么样

public void yourMethod() {
    ...
    Process process = new ProcessBuilder(...).start(); 
    //wait 5 secs or kill the process
    waitForOrKill(process, TimeUnit.SECONDS.toMillis(5));
    ...
}

public static void waitForOrKill(Process self, long numberOfMillis) {
    ProcessRunner runnable = new ProcessRunner(self);
    Thread thread = new Thread(runnable);
    thread.start();
    runnable.waitForOrKill(numberOfMillis);
}

protected static class ProcessRunner implements Runnable {
    Process process;
    private boolean finished;

    public ProcessRunner(Process process) {
        this.process = process;
    }

    public void run() {
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            // Ignore
        }
        synchronized (this) {
            notifyAll();
            finished = true;
        }
    }

    public synchronized void waitForOrKill(long millis) {
        if (!finished) {
            try {
                wait(millis);
            } catch (InterruptedException e) {
                // Ignore
            }
            if (!finished) {
                process.destroy();
            }
        }
    }
}

回答by nuwan

just modified a bit according to my requirement. time out is 10 seconds here. process is getting destroyed after 10 seconds if it is not exiting.

只是根据我的要求修改了一点。这里的超时时间是 10 秒。如果进程未退出,则 10 秒后进程将被销毁。

public static void main(String arg[]) {

    try {
        Process p = Runtime.getRuntime().exec("\"C:/Program Files/VanDyke Software/SecureCRT/SecureCRT.exe\"");
        long now = System.currentTimeMillis(); 
        long timeoutInMillis = 1000L * 10; 
        long finish = now + timeoutInMillis; 
        while ( isAlive( p ) ) { 
            Thread.sleep( 10 ); 
            if ( System.currentTimeMillis() > finish ) {
                p.destroy();
            }
        }
    } catch (Exception err) {
        err.printStackTrace();
    }
}

public static boolean isAlive( Process p ) {  
    try {  
        p.exitValue();  
        return false;  
    } catch (IllegalThreadStateException e) {  
        return true;  
    }  
}  

回答by Aleksander Blomsk?ld

If you're using Java 8 you could simply use the new waitFor with timeout:

如果您使用的是 Java 8,您可以简单地使用带有 timeout的新waitFor

Process p = ...
if(!p.waitFor(1, TimeUnit.MINUTE)) {
    //timeout - kill the process. 
    p.destroy(); // consider using destroyForcibly instead
}