2016-01-12 168 views
0

我正在使用Java Executors.newWorkStealingPool();並行運行多個命令。由於其中一些任務預計會超時,所以我爲它們添加了2秒的超時時間。進程不終止

ProcessBuilder pb = new ProcessBuilder(cmd.split(" ")); 
Process p = null; 
StringBuilder result = new StringBuilder(); 
try { 
    p = pb.start(); 
    p.waitFor(2000, TimeUnit.MILLISECONDS); 
    BufferedReader errreader = 
    new BufferedReader(new InputStreamReader(p.getErrorStream())); 
    BufferedReader outreader = new BufferedReader(new InputStreamReader(p.getInputStream())); 
    String line = "";   
    while ((line = outreader.readLine())!= null) 
    result.append(line + "\n"); 
    while ((line = errreader.readLine())!= null) 
     result.append(line + "\n"); 
    outreader.close(); 
    errreader.close(); 
    } catch (InterruptedException e) { 
     result.append("INTERRUPTED"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     System.exit(-1); 
    } 
    finally { 
     p.destroy(); 
    } 
    .... 
    return b; // b is boolean 

提交任務看起來像這樣

List<ImmutablePair> curJobs = new ArrayList<ImmutablePair>(); 
for (int i = 0; i < allMutants.size(); i++) { 
    String mutant = allMutants.get(i); 
    t = executor.submit(new mutTask(mutant)); 
    ImmutablePair pair = new ImmutablePair(mutant, t); 
    curJobs.add(pair); 
    } 

最後。我在下面的循環中收集結果。

// data collection loop 
for (int i = 0; i< curJobs.size(); i++) { 
     ImmutablePair p = curJobs.get(i); 
     String m= (String) p.getLeft(); 
    System.out.println(m); 
     t = (Future<Boolean>) p.getRight(); 
    try { 
     boolean res; 
     try { 
      res = t.get(2000L, TimeUnit.MILLISECONDS); 

     } catch (TimeoutException e) { 
      res = true; 
     } 
     finally { 
      t.cancel(true); 
     }} 

問題是,超時似乎並沒有終止程序中定義的某些命令或進程。幾分鐘後數據收集循環變得非常緩慢。 ps的結果顯示了一些超出指定超時運行並保持CPU繁忙的作業。我的配置是CentOS上的JDK8。

+1

所以輸出,從JavaDoc中,我們知道*「造成當前線程等待,如果必要的話,直到由該Process對象表示的子進程已經終止,或經過指定的等待時間。「*,這意味着此方法將在進程存在或指定時間過去時返回,這意味着進程可能仍在運行。接下來,您將讀取流程輸出的內容,這意味着如果流程仍然處於崩潰狀態,則它仍在處理輸出或阻塞......通常我使用子線程「Thread」來讀取輸入,當waitFor '返回,停止這些線程 – MadProgrammer

+0

...然後銷燬進程 – MadProgrammer

+0

謝謝。正如你注意到的那樣,問題是沒有檢查'p.waitFor(2000,TimeUnit.MILLISECONDS);'的輸出。 – Amin

回答

0

正如@MadProgrammer指出的問題是讀取/ err緩衝區,以防進程終止。爲了解決這個問題,你需要檢查的p.waitFor(2000, TimeUnit.MILLISECONDS);

try { 
     p = pb.start(); 
     boolean timeout = !p.waitFor(2000, TimeUnit.MILLISECONDS); 
     if (!timeout){ 
      BufferedReader errreader = 
        new BufferedReader(new InputStreamReader(p.getErrorStream())); 
      BufferedReader outreader = 
        new BufferedReader(new InputStreamReader(p.getInputStream())); 

      String line = ""; 
      while ((line = outreader.readLine())!= null) 
       result.append(line + "\n"); 
      while ((line = errreader.readLine())!= null) 
        result.append(line + "\n"); 
      outreader.close(); 
      errreader.close(); 
     } 

    } catch ...