Java本机进程超时

Java本机进程超时,java,process,Java,Process,目前,我使用以下命令执行本机进程: java.lang.Process process = Runtime.getRuntime().exec(command); int returnCode = process.waitFor(); 假设我不等待程序返回,而是希望在经过一定时间后终止。如何执行此操作?这是Plexus CommandlineUtils执行此操作的方式: Process p; p = cl.execute(); ... if ( timeoutInSeconds <

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

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

假设我不等待程序返回,而是希望在经过一定时间后终止。如何执行此操作?

这是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;
    }
}
过程p;
p=cl.execute();
...

如果(timeoutingseconds您需要一个2.线程来中断调用.waitFor()的线程; 需要进行一些非常重要的同步,以使其具有健壮性,但最基本的是:

超时线程:

 Thread.sleep(timeout);
 processThread.interrupt();
进程线程:

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

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

比如说,

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
}
private静态最终执行器服务线程池
=Executors.newCachedThreadPool();
私有静态T timedCall(可调用c、长超时、TimeUnit TimeUnit)
抛出InterruptedException、ExecutionException、TimeoutException
{
未来任务=新的未来任务(c);
线程池执行(任务);
返回任务.get(超时,时间单位);
}
final java.lang.Process[]进程=新进程[1];
试一试{
int returnCode=timedCall(新的可调用(){
公共整数调用()引发异常{
进程[0]=Runtime.getRuntime().exec(命令);
返回进程[0]。waitFor();
}
},超时,时间单位为秒);
}捕获(超时异常e){
进程[0]。销毁();
//在这里处理超时
}
如果重复执行此操作,线程池会更高效,因为它会缓存线程。

方法如何


只是根据我的要求修改了一点。这里的超时时间是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;  
    }  
}  

如果您使用的是Java 8或更高版本(Android的API 26或更高版本),您只需使用:


EWWW…所以每10毫秒它就依赖于p.exitValue()抛出IllegalThreadStateException来表示“仍在运行”@OgrePsalm33这很糟糕,但遗憾的是Java没有更好的方法升级到Java 7。Java8给出了一个“p.isAlive()”为什么循环?为什么不运行一个会检查“有效性”的TimerTask呢仅在超时过期时才执行一次?例如,这里的句柄超时可能会更健壮一些。我使用了两种机制,但对于最简单的情况,可以使用如下内容:
catch(TimeoutException e){System.exit(-1);}
类型参数不能是基元类型。请将
int
替换为
Integer
。尽管指定超时后将调用TimeoutException,但命令本身将继续在另一个线程的后台执行,除非在抛出
TimeoutException
时调用
destroy()
。(即使在对执行器进行
shutdownNow()
调用后也会看到同样的情况)
线程池应该是在应用程序停止时,否则它可能会阻止JVM终止长达60秒(newCachedThreadPool()的工作线程的最大空闲时间
)因为非守护进程工作线程仍然处于活动状态。请在这里找到一个好的实践和一些解释:在Android中,它只在
API26
及更高版本中可用。这不会“返回退出”code@Bogdan,如果(且仅当)
waitFor(…)
返回true,则可以调用以获取退出代码。
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;  
    }  
}  
Process p = ...
if(!p.waitFor(1, TimeUnit.MINUTE)) {
    //timeout - kill the process. 
    p.destroy(); // consider using destroyForcibly instead
}