Java starts async processes

I am trying to start an asynchronous process and I do not want the program to wait for the end of these processes. I found this question on how to run a shell script asynchronously from within a Java program , but I don't have the answer I'm looking for.

What I do is I just start bash processes, and once started, I don't want the Java program to wait until it finishes. This is what I did:

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 printed another fingerprint at the end of the main method, so I get this output:

Task Dispatched
Task Dispatched
End of psvm

      

However, the program does not end because these two processes are not completed.

How can I solve this problem?

+3


source to share


2 answers


You need your thread to be a demon thread. Use setDaemon(true)

before starting.

 commandLineThread.setDaemon(true);

      

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

Edit:



From your comments, you need to execute the command even if the JVM is about to exit. I assume the variable command

contains the script you want to run? You can make two changes to make the program behave the way I think you want.

  • Start bash with -c

    to execute your command, then you don't need to post things to the output stream.
  • Start the process before starting the thread waiting to exit.

The resulting code will look something like this:

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

      

+4


source


You are reading the output streams of your process and this is the reason why your Java program is not exiting:

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

      



Reading your stream will block your code.

You may like to redirect the output of a running process to a log file and read it later.

+1


source







All Articles