2009-08-07 32 views
39

Tại thời điểm này tôi thực hiện một quá trình tự nhiên sử dụng như sau:java mẹ đẻ Process timeout

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

Giả sử thay vì chờ cho chương trình trở lại tôi muốn chấm dứt nếu một số tiền nhất định của thời gian đã trôi qua. Làm thế nào để tôi làm điều này?

+0

Hãy tìm một thực hành tốt và một số explantion đây: Wulfaz

Trả lời

18

Đây là cách Plexus CommandlineUtils làm nó:

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; 
    } 
} 
+8

Ewwww ... vì vậy cứ 10 mili giây nó dựa trên p.exitValue() ném IllegalThreadStateException để cho biết "vẫn đang chạy"? –

+0

@ OgrePsalm33 Thật kinh khủng, nhưng thật đáng buồn Java không mang lại cách nào đẹp hơn cho Java 7. Java8 đưa ra một "p.isAlive()" – leonbloy

+1

Tại sao vòng lặp lại? Tại sao không chạy TimerTask mà sẽ kiểm tra "aliveness" chỉ một lần khi hết hạn thời gian chờ? – Stan

2

Bạn sẽ cần một 2. thread ngắt thread gọi .waitFor(); Một số đồng bộ hóa không tầm thường sẽ là cần thiết để làm cho nó mạnh mẽ, nhưng những điều cơ bản là:

TimeoutThread:

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

ProcessThread:

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

Tất cả các câu trả lời khác là chính xác nhưng nó có thể được thực hiện mạnh mẽ hơn và hiệu quả hơn khi sử dụng FutureTask.

Ví dụ,

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 
} 

Nếu bạn làm điều này nhiều lần, hồ bơi thread là hiệu quả hơn vì nó lưu trữ các chủ đề.

+0

Thời gian chờ xử lý ở đây có thể mạnh mẽ hơn một chút cho một ví dụ. Tôi có một vài cơ chế tôi sử dụng, nhưng đối với trường hợp đơn giản nhất, sử dụng một cái gì đó như: 'catch (TimeoutException e) {System.exit (-1);}' –

+0

Đối số kiểu không thể là kiểu nguyên thủy. Vui lòng thay thế 'int' bằng' Số nguyên'. – naXa

6

gì về cách 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(); 
      } 
     } 
    } 
} 
4

chỉ thay đổi một chút theo yêu cầu của tôi. hết thời gian là 10 giây ở đây. quá trình sẽ bị phá hủy sau 10 giây nếu nó không thoát.

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; 
    } 
} 
14

Nếu bạn đang sử dụng Java 8 bạn chỉ có thể sử dụng mới waitFor with timeout:

Process p = ... 
if(!p.waitFor(1, TimeUnit.MINUTE)) { 
    //timeout - kill the process. 
    p.destroy(); // consider using destroyForcibly instead 
} 
Các vấn đề liên quan