在 Java 中启动、停止和收听进程

Start, stop and listen to a process in Java

我想用 Runtime.exec() 启动一个进程。然后我想知道(听)进程何时退出。另外,如果满足某些条件,我想手动停止该过程。

我现在的代码是:

public class ProcessManager extends Thread{
    private static ProcessManager manager;

    Process process;

    private ProcessManager(){

    }

    public static ProcessManager getInstance(){
        if(manager==null){
            manager=new ProcessManager();
        }
        return manager;
    }

    public void run(){
        Runtime runtime = Runtime.getRuntime();
        process = runtime.exec("c:\windows\system32\notepad.exe");
        //cleanup();
    }
    public void cleanup(){
        //I want to do stuffs until the program really ends;
    }

    //called to manually stop the process
    public void stopProcess(){
        if(process!=null){
            //TODO: stop the process;
        }
    }
}

如代码所示,我的程序就像notepad.exe,弹出一个window,然后立即returns。如何监听程序的状态,等待程序关闭,以及显式关闭?

How can I listen to the status of the program, and wait until it is closed, as well as close it explicitly?

您可以使用Process#waitFor()

// cause this process to stop until process p is terminated
         p.waitFor();

JavaDoc所说

The java.lang.Process.waitFor() method causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.

我不建议直接使用 Runtime.exec()。它并不像看起来那么简单。不错的文章 "When Runtime.exec() won't" 详细描述了这些陷阱。例如带有 waitFor():

的简单代码
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);

不会产生任何输出并挂起,因为通常您需要在单独的线程中处理输入、输出和错误流。

相反,您可以使用 Apache Commons Exec 库来为您处理:

String line = "notepad.exe";
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
System.out.println("Process exitValue: " + exitValue);

下面是手动终止异步进程的更复杂示例:

String line = "notepad.exe";
CommandLine cmdLine = CommandLine.parse(line);
ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout);
Executor exec = new DefaultExecutor();
DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
exec.execute(cmdLine, handler);
// wait for script to run
Thread.sleep(2000);
// terminate it manually if needed
if (someCondition) {
    watchdog.destroyProcess();
}
// wait until the result of the process execution is propagated
handler.waitFor(WAITFOR_TIMEOUT);
System.out.println("Process exitValue: " + handler.getExitValue());