Java run async processes

半世苍凉 提交于 2019-12-30 09:20:14

问题


I am trying to run an async process and I do not want the program to wait until the end of these processes executions. I found this question how to run shell script asynchronously from within Java program but it doesn't have the answer that I am looking for.

What I am doing is I am simply running bash processes and after I run it, I do not want the Java program to wait until it's finished. This is what I have done:

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");
}

I also put another print out at the end of the main method so I get this output:

Task Dispatched
Task Dispatched
End of psvm

However the program does not terminate as these two processes have not terminated.

How can I solve this issue?


回答1:


You need to make your thread a daemon thread. Use setDaemon(true) before starting it.

 commandLineThread.setDaemon(true);

A daemon thread is a thread that does not prevent the JVM from exiting. See this question: What is Daemon thread in Java? for more information about daemon threads.

Edit:

By judging from your comments you need the command to run even though the JVM is about to exit. I assume the command variable contains the script you want to run? You could make two changes to make the program behave as I think you want.

  1. Start bash with -c to execute your command, then you do not have to send things to an output stream.
  2. Start the process before starting your thread that waits for the output.

The resulting code would look something like:

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");
}



回答2:


You are reading the output streams of your process, and thats the reason your java program does not exit:

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

Your stream reading will keep blocking your code.

You may like to redirect output of your launched process to a log file and read that later.




回答3:


           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();


来源:https://stackoverflow.com/questions/30706704/java-run-async-processes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!