问题
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.
- Start bash with
-c
to execute your command, then you do not have to send things to an output stream. - 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