目前我使用下面的執行本機進程:Java本機進程超時
java.lang.Process process = Runtime.getRuntime().exec(command);
int returnCode = process.waitFor();
假設,而不是等待程序返回我想終止,如果在一定的時間量已過去。我該怎麼做呢?
目前我使用下面的執行本機進程:Java本機進程超時
java.lang.Process process = Runtime.getRuntime().exec(command);
int returnCode = process.waitFor();
假設,而不是等待程序返回我想終止,如果在一定的時間量已過去。我該怎麼做呢?
這是叢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;
}
}
你需要一個2線程中斷調用.waitFor()線程;將需要 一些不平凡的同步,使之強勁,但基本是:
TimeoutThread:
Thread.sleep(timeout);
processThread.interrupt();
ProcessThread:
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);
}
try {
int returnCode = timedCall(new Callable<Integer>() {
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
}
如果這樣反反覆覆,線程池是更有效,因爲它緩存的線程。
這裏的句柄超時對於一個例子來說可能更健壯一些。我有一些我使用的機制,但是對於最簡單的情況,使用如下形式:'catch(TimeoutException e){System.exit(-1);}' – 2012-11-10 15:49:19
類型參數不能是原始類型。請用'Integer'替換int。 – naXa 2014-09-22 15:15:23
怎麼樣的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();
}
}
}
}
根據我的要求只是修改了一下。超時在這裏是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,你可以簡單地使用新waitFor with timeout:
Process p = ...
if(!p.waitFor(1, TimeUnit.MINUTE)) {
//timeout - kill the process.
p.destroy(); // consider using destroyForcibly instead
}
請找到一個很好的做法,一些explantion這裏: –
Wulfaz
2013-07-16 13:25:31