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
java native Process timeout
提问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
}