Java运行异步进程

时间:2015-06-08 10:26:00

标签: java multithreading asynchronous process processbuilder

我正在尝试运行异步进程,我不希望程序等到这些进程执行结束。我发现了这个问题how to run shell script asynchronously from within Java program,但它没有我想要的答案。

我正在做的是我只是运行bash进程,在运行它之后,我不希望Java程序等到它完成。这就是我所做的:

public void runCommandLine(String directory) throws IOException {
    Thread commandLineThread = new Thread(() -> {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(
                    "/bin/bash");
            processBuilder.directory(new File(directory));
            Process process = processBuilder.start();
            try (OutputStreamWriter osw = new OutputStreamWriter(process.getOutputStream())) {
                osw.write(command);
            }
            printStream(process.getErrorStream(), true);
            printStream(process.getInputStream(), true);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    });
    commandLineThread.start();
    System.out.println("Task Dispatched");
}

我还在main方法的末尾添加了另一个打印输出,所以我得到了这个输出:

Task Dispatched
Task Dispatched
End of psvm

但是程序没有终止,因为这两个进程没有终止。

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

您需要使您的线程成为守护程序线程。在启动之前使用setDaemon(true)

 commandLineThread.setDaemon(true);

守护程序线程是一个不阻止JVM退出的线程。有关守护程序线程的详细信息,请参阅此问题:What is Daemon thread in Java?

编辑:

通过判断您的评论,即使JVM即将退出,您也需要运行命令。我假设command变量包含您要运行的脚本?您可以进行两项更改,以使程序按照我的意愿运行。

  1. 使用-c启动bash以执行命令,然后您不必将内容发送到输出流。
  2. 在启动等待输出的线程之前启动该过程。
  3. 结果代码如下所示:

    public void runCommandLine(String directory) throws IOException {
        ProcessBuilder processBuilder = new ProcessBuilder(
                        "/bin/bash -c " + command);
        processBuilder.directory(new File(directory));
        Process process = processBuilder.start();
        Thread commandLineThread = new Thread(() -> {
            try {
                printStream(process.getErrorStream(), true);
                printStream(process.getInputStream(), true);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
        commandLineThread.setDaemon(true);
        commandLineThread.start();
        System.out.println("Task Dispatched");
    }
    

答案 1 :(得分:0)

您正在阅读流程的输出流,这就是您的Java程序无法退出的原因:

        printStream(process.getErrorStream(), true);
        printStream(process.getInputStream(), true);

您的信息流阅读将阻止您的代码。

您可能希望将已启动进程的输出重定向到日志文件,稍后再阅读。

答案 2 :(得分:0)

           Thread commandLineThread = new Thread(() -> {
            try {
                BufferedReader br=new BufferedReader(
                        new InputStreamReader(
                                process.getInputStream()));
                String line;

                while((line=br.readLine())!=null){
                    System.out.println(line);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
        commandLineThread.setDaemon(true);
        commandLineThread.start();