0

При запуске внешнего скрипта я хочу читать ErrorStream и OutputStream этого скрипта одновременно и отдельно, а затем обрабатывать их дальше. Поэтому я запускаю Thread для одного из потоков. К сожалению, Process, похоже, не waitForThread, который должен быть завершен, но возврат после того, как поток без потока не имеет никакого ввода.Process.waitFor() a thread

В двух словах, вот что я делаю:

ProcessBuilder pb = new ProcessBuilder(script); 
final Process p = pb.start(); 

new Thread(new Runnable() { 
    public void run() { 
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream())); 
    ...read lines and process them... 
    } 
}).start(); 

BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); 
...read lines and process them... 

int exitValue = p.waitFor(); 
p.getOutputStream().close(); 
return exitValue; 

Есть ли возможность waitForThread быть прекращено?

+0

Возможно, просто используйте [Commons Exec] (http://commons.apache.org/proper/commons-exec//) - не нужно изобретать колесо. –

+1

Было бы полезно, если бы вы отправили свой настоящий код. Две вещи, вы никогда не запускаете поток чтения потока ввода; и вы не должны закрывать поток вывода процессов до его завершения. – Perception

+0

@Perception: Извините за неполный и, следовательно, дефектный код. Я исправил его выше. – stan

ответ

0

Вы можете использовать Thread.join(...) ждать Thread закончить. Обратите внимание, что вызов вызывает InterruptedException, если текущий поток получает прерывание перед потоком, который вы ожидаете завершения.

+0

Это делает трюк. Спасибо! – stan

+0

любой шанс, что вы отредактируете вышеуказанный код, чтобы отразить рабочие изменения? – TiGer

+0

Что? Чтобы вы могли скопировать и вставить его? Ни за что! –

1

Вот общий код для выполнения того, что вы хотите сделать. В этом случае есть как вход, так и выход: я прокладываю трубопровод someFile в процесс и подаю вывод на System.out. Files.copy() и ByteStreams.copy() - это только удобные методы Guava для подключения InputStream к OutputStream. Затем мы ожидаем завершения команды.

final Process pr = Runtime.getRuntime().exec(cmd); 

new Thread() { 
    public void run() { 
     try (OutputStream stdin = pr.getOutputStream()) { 
      Files.copy(someFile, stdin); 
     } 
     catch (IOException e) { e.printStackTrace(); } 
    } 
}.start(); 

new Thread() { 
    public void run() { 
     try (InputStream stdout = pr.getInputStream()) { 
      ByteStreams.copy(stdout, System.out); 
     } 
     catch (IOException e) { e.printStackTrace(); } 
    } 
}.start();    

int exitVal = pr.waitFor(); 
if(exitVal == 0) 
    System.out.println("Command succeeded!"); 
else  
    System.out.println("Exited with error code " + exitVal); 

Более подробная версия, если вы работаете до Java 7 с блока примерочных с-ресурсами:

final Process pr = Runtime.getRuntime().exec(cmd); 

new Thread() { 
    public void run() { 
     OutputStream stdin = null; 
     try { 
      Files.copy(someFile, stdin = pr.getOutputStream()); 
     } 
     catch (IOException e) { e.printStackTrace(); } 
     finally { 
      if(stdin != null) { 
       try { stdin.close(); } 
       catch (IOException e) { e.printStackTrace(); } 
      } 
     }    
    } 
}.start(); 

new Thread() { 
    public void run() { 
     InputStream stdout = null; 
     try { 
      ByteStreams.copy(stdout = pr.getInputStream(), System.out); 
     } 
     catch (IOException e) { e.printStackTrace(); } 
     finally { 
      if(stdout != null) { 
       try { stdout.close(); } 
       catch (IOException e) { e.printStackTrace(); } 
      } 
     }    
    } 
}.start();    

int exitVal = pr.waitFor(); 
if(exitVal == 0) 
    System.out.println("Command succeeded!"); 
else  
    System.out.println("Exited with error code " + exitVal); 
+0

Спасибо за ваш ответ. К сожалению, использование «Commons Exec» для меня не работает. Нет потока 'waitFor' потокового потока. Но я мог бы решить проблему, используя решение Стефана выше. – stan

+0

Не знаете, где вы видите Commons Exec в моем ответе. Метод 'Process' и его' waitFor() 'доступны в стандартной Java. –

+0

Очень полезный ответ (первый код), но мне пришлось использовать «IOUtils» вместо «ByteStreams» (второй поток). –

Смежные вопросы