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?
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.
-c
to execute your command, then you do not have to send things to an output stream.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");
}