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?
source to share
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");
}
source to share
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.
source to share