如何使用带参数的exitValue()?

一篇非常好的文章(当Runtime.exec()不会)时说:你不希望你的程序阻塞等待外部进程的唯一可能的时间你将使用exitValue()而不是waitFor()可能永远不会完成 我宁愿将一个名为waitFor的布尔参数传递给exitValue()方法,以确定当前线程是否应该等待,而不是使用waitFor()方法。 布尔值会更有用,因为exitValue()是此方法的更合适的名称,并且两个方法不必在不同条件下执行相同的function。 这种简单的条件判别是输入参数的范畴。

我有完全相同的情况,我的系统调用将启动一个将继续运行的进程,直到用户决定杀死它。 如果我使用’(process.waitFor()== 0)’它将阻止程序,因为进程将无法完成。 上面文章中的作者建议exitValue()可以与’waitFor’参数一起使用。 有人尝试过吗? 任何例子都会有所帮助。

码:

//启动ProcessBuilder,’str’包含一个命令

ProcessBuilder pbuilder = new ProcessBuilder(str); pbuilder.directory(new File("/root/workspace/Project1")); pbuilder.redirectErrorStream(true); Process prcs = pbuilder.start(); AForm.execStatustext.append("\n=> Process is:" + prcs); // Read output StringBuilder out = new StringBuilder(); BufferedReader bfrd = new BufferedReader(new InputStreamReader(process.getInputStream())); String current_line = null, previous_line = null; while ((current_line = bfrd.readLine()) != null) { if (!line.equals(previous_line)) { previous_line = current_line; out.append(current_line).append('\n'); //System.out.println(line); } } //process.getInputStream().close(); // Send 'Enter' keystroke through BufferedWriter to get control back BufferedWriter bfrout = new BufferedWriter(new OutputStreamWriter(prcs.getOutputStream())); bfrout.write("\\r"); bfrout.newLine(); bfrout.flush(); bfrout.write("\\r"); bfrout.newLine(); bfrout.flush(); //process.getOutputStream().close();*/ if (prcs.waitFor() == 0) System.out.println("Commands executed successfully"); System.exit(0); 

在主线程中使用waitFor之前,创建另一个线程(子)并在此新线程中为终止案例构造逻辑。 例如,等待10秒。 如果满足条件,则从子线程中断主线程ant处理主线程上的以下逻辑。

以下代码创建一个子线程来调用该进程,主线程完成其工作,直到子进程成功完成。

  import java.io.IOException; public class TestExecution { public boolean myProcessState = false; class MyProcess implements Runnable { public void run() { //------ Process process; try { process = Runtime.getRuntime().exec("your command"); process.waitFor(); int processExitValue = process.exitValue(); if(processExitValue == 0) { myProcessState = true; } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void doMyWork() { MyProcess myProcess = new MyProcess(); Thread myProcessExecuter = new Thread(myProcess); myProcessExecuter.start(); while(!myProcessState) { // do your job until the process exits with success } } public static void main(String[] args) { TestExecution testExecution = new TestExecution(); testExecution.doMyWork(); } } 

这是我用来启动外部进程的一些库代码的“粗略”示例。

基本上,这使用三个线程。 第一个用于执行实际命令,然后等待它存在。

另外两个处理进程输出和输入流。 这使得这些彼此独立阻止了一个人阻挡另一个人的能力。

然后整个事情与一个听众联系起来,当事情发生时通知他。

error handling可能会更好(因为失败条件对于什么/谁实际失败有点不清楚),但基本概念是……

这意味着您可以启动该过程而不关心…(直到您想要)

 import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class TestBackgroundProcess { public static void main(String[] args) { new TestBackgroundProcess(); } public TestBackgroundProcess() { BackgroundProcess bp = new BackgroundProcess("java", "-jar", "dist/BackgroundProcess.jar"); bp.setListener(new ProcessListener() { @Override public void charRead(BackgroundProcess process, char value) { } @Override public void lineRead(BackgroundProcess process, String text) { System.out.println(text); } @Override public void processFailed(BackgroundProcess process, Exception exp) { System.out.println("Failed..."); exp.printStackTrace(); } @Override public void processCompleted(BackgroundProcess process) { System.out.println("Completed - " + process.getExitValue()); } }); System.out.println("Execute command..."); bp.start(); bp.send("dir"); bp.send("exit"); System.out.println("I'm not waiting here..."); } public interface ProcessListener { public void charRead(BackgroundProcess process, char value); public void lineRead(BackgroundProcess process, String text); public void processFailed(BackgroundProcess process, Exception exp); public void processCompleted(BackgroundProcess process); } public class BackgroundProcess extends Thread { private List commands; private File startIn; private int exitValue; private ProcessListener listener; private OutputQueue outputQueue; public BackgroundProcess(String... cmds) { commands = new ArrayList<>(Arrays.asList(cmds)); outputQueue = new OutputQueue(this); } public void setStartIn(File startIn) { this.startIn = startIn; } public File getStartIn() { return startIn; } public int getExitValue() { return exitValue; } public void setListener(ProcessListener listener) { this.listener = listener; } public ProcessListener getListener() { return listener; } @Override public void run() { ProcessBuilder pb = new ProcessBuilder(commands); File startIn = getStartIn(); if (startIn != null) { pb.directory(startIn); } pb.redirectError(); Process p; try { p = pb.start(); InputStreamConsumer isc = new InputStreamConsumer(p.getInputStream(), this, getListener()); outputQueue.init(p.getOutputStream(), getListener()); outputQueue.start(); p.waitFor(); isc.join(); outputQueue.terminate(); outputQueue.join(); ProcessListener listener = getListener(); if (listener != null) { listener.processCompleted(this); } } catch (InterruptedException ex) { ProcessListener listener = getListener(); if (listener != null) { listener.processFailed(this, ex); } } catch (IOException ex) { ProcessListener listener = getListener(); if (listener != null) { listener.processFailed(this, ex); } } } public void send(String cmd) { outputQueue.send(cmd); } } public class OutputQueue extends Thread { private List cmds; private OutputStream os; private ProcessListener listener; private BackgroundProcess backgroundProcess; private ReentrantLock waitLock; private Condition waitCon; private boolean keepRunning = true; public OutputQueue(BackgroundProcess bp) { backgroundProcess = bp; cmds = new ArrayList<>(25); waitLock = new ReentrantLock(); waitCon = waitLock.newCondition(); } public ProcessListener getListener() { return listener; } public OutputStream getOutputStream() { return os; } public BackgroundProcess getBackgroundProcess() { return backgroundProcess; } public void init(OutputStream outputStream, ProcessListener listener) { os = outputStream; this.listener = listener; } public void send(String cmd) { waitLock.lock(); try { cmds.add(cmd); waitCon.signalAll(); } finally { waitLock.unlock(); } } public void terminate() { waitLock.lock(); try { cmds.clear(); keepRunning = false; waitCon.signalAll(); } finally { waitLock.unlock(); } } @Override public void run() { try { Thread.sleep(500); } catch (InterruptedException ex) { } BackgroundProcess backgroundProcess = getBackgroundProcess(); ProcessListener listener = getListener(); OutputStream outputStream = getOutputStream(); try { while (keepRunning) { while (cmds.isEmpty() && keepRunning) { waitLock.lock(); try { waitCon.await(); } catch (Exception exp) { } finally { waitLock.unlock(); } } if (!cmds.isEmpty()) { waitLock.lock(); try { while (!cmds.isEmpty()) { String cmd = cmds.remove(0); System.out.println("Send " + cmd); outputStream.write(cmd.getBytes()); outputStream.write('\n'); outputStream.write('\r'); outputStream.flush(); } } finally { waitLock.unlock(); } } } } catch (IOException ex) { if (listener != null) { listener.processFailed(backgroundProcess, ex); } } } } public class InputStreamConsumer extends Thread { private InputStream is; private ProcessListener listener; private BackgroundProcess backgroundProcess; public InputStreamConsumer(InputStream is, BackgroundProcess backgroundProcess, ProcessListener listener) { this.is = is; this.listener = listener; this.backgroundProcess = backgroundProcess; start(); } public ProcessListener getListener() { return listener; } public BackgroundProcess getBackgroundProcess() { return backgroundProcess; } @Override public void run() { BackgroundProcess backgroundProcess = getBackgroundProcess(); ProcessListener listener = getListener(); try { StringBuilder sb = new StringBuilder(64); int in = -1; while ((in = is.read()) != -1) { char value = (char) in; if (listener != null) { listener.charRead(backgroundProcess, value); if (value == '\n' || value == '\r') { if (sb.length() > 0) { listener.lineRead(null, sb.toString()); sb.delete(0, sb.length()); } } else { sb.append(value); } } } } catch (IOException ex) { listener.processFailed(backgroundProcess, ex); } } } } 

如果我使用’(process.waitFor()== 0)’它将阻止程序,因为进程将无法完成。

不,不会。 它会阻塞线程。 这就是你有线程的原因。

上面文章中的作者建议exitValue()可以与’waitFor’参数一起使用

不,他没有。 如果有人问过他,他正在谈论他将如何设计它。 但他们没有,他没有。

有人尝试过吗?

你不能。 它不存在。