java本机进程超时
目前,我使用以下命令执行本机进程:
java.lang.Process process = Runtime.getRuntime().exec(command);
int returnCode = process.waitFor();
假设我希望在经过一定时间后终止,而不是等待程序返回。 我该怎么做呢?
deltanovember asked 2020-07-22T02:28:34Z
6个解决方案
51 votes
所有其他响应都是正确的,但是可以使用FutureTask使它更健壮和有效。
例如,
private static final ExecutorService THREAD_POOL
= Executors.newCachedThreadPool();
private static T timedCall(Callable c, long timeout, TimeUnit timeUnit)
throws InterruptedException, ExecutionException, TimeoutException
{
FutureTask task = new FutureTask(c);
THREAD_POOL.execute(task);
return task.get(timeout, timeUnit);
}
try {
int returnCode = timedCall(new Callable() {
public Integer call() throws Exception {
java.lang.Process process = Runtime.getRuntime().exec(command);
return process.waitFor();
}
}, timeout, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// Handle timeout here
}
如果重复执行此操作,则线程池会更高效,因为它会缓存线程。
ZZ Coder answered 2020-07-22T02:30:06Z
21 votes
如果您使用的是Java 8,则可以将新的waitFor与超时一起使用:
Process p = ...
if(!p.waitFor(1, TimeUnit.MINUTE)) {
//timeout - kill the process.
p.destroy(); // consider using destroyForcibly instead
}
Aleksander Blomskøld answered 2020-07-22T02:30:26Z
19 votes
这是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;
}
}
Rich Seller answered 2020-07-22T02:29:37Z
6 votes
那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();
}
}
}
}
mickthompson answered 2020-07-22T02:30:46Z
4 votes
只是根据我的要求做了一些修改。 这里的超时时间是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;
}
}
nuwan answered 2020-07-22T02:31:06Z
2 votes
您需要一个2.线程来中断调用.waitFor()的线程。为了使其健壮,将需要一些非同寻常的同步,但基础知识是:
TimeoutThread:
Thread.sleep(timeout);
processThread.interrupt();
ProcessThread:
try {
proc.waitFor();
} catch (InterruptedException e) {
proc.destroy();
}
nos answered 2020-07-22T02:31:35Z