Java 运行 异步进程
Java run async processes
我正在尝试 运行 一个异步进程,我不希望程序等到这些进程执行结束。我找到了这个问题 how to run shell script asynchronously from within Java program,但它没有我要找的答案。
我正在做的只是 运行ning bash 进程,在我 运行 它之后,我不希望 Java 程序等到它完成的。这就是我所做的:
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");
}
我还在主要方法的末尾打印了另一个,所以我得到了这个输出:
Task Dispatched
Task Dispatched
End of psvm
但是程序并没有终止,因为这两个进程还没有终止。
我该如何解决这个问题?
您需要将您的线程设为守护线程。在开始之前使用 setDaemon(true)
。
commandLineThread.setDaemon(true);
守护线程是不会阻止 JVM 退出的线程。请参阅此问题:What is Daemon thread in Java? 了解有关守护线程的更多信息。
编辑:
根据您的评论判断,即使 JVM 即将退出,您也需要 运行 命令。我假设 command
变量包含您想要 运行 的脚本?您可以进行两项更改以使程序按照我认为的方式运行。
- 使用
-c
启动 bash 来执行您的命令,然后您不必将内容发送到输出流。
- 在启动等待输出的线程之前启动进程。
生成的代码类似于:
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");
}
您正在读取进程的输出流,这就是您的 java 程序没有退出的原因:
printStream(process.getErrorStream(), true);
printStream(process.getInputStream(), true);
你的流阅读会一直阻塞你的代码。
您可能希望将已启动进程的输出重定向到日志文件并稍后阅读。
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();
我正在尝试 运行 一个异步进程,我不希望程序等到这些进程执行结束。我找到了这个问题 how to run shell script asynchronously from within Java program,但它没有我要找的答案。
我正在做的只是 运行ning bash 进程,在我 运行 它之后,我不希望 Java 程序等到它完成的。这就是我所做的:
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");
}
我还在主要方法的末尾打印了另一个,所以我得到了这个输出:
Task Dispatched
Task Dispatched
End of psvm
但是程序并没有终止,因为这两个进程还没有终止。
我该如何解决这个问题?
您需要将您的线程设为守护线程。在开始之前使用 setDaemon(true)
。
commandLineThread.setDaemon(true);
守护线程是不会阻止 JVM 退出的线程。请参阅此问题:What is Daemon thread in Java? 了解有关守护线程的更多信息。
编辑:
根据您的评论判断,即使 JVM 即将退出,您也需要 运行 命令。我假设 command
变量包含您想要 运行 的脚本?您可以进行两项更改以使程序按照我认为的方式运行。
- 使用
-c
启动 bash 来执行您的命令,然后您不必将内容发送到输出流。 - 在启动等待输出的线程之前启动进程。
生成的代码类似于:
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");
}
您正在读取进程的输出流,这就是您的 java 程序没有退出的原因:
printStream(process.getErrorStream(), true);
printStream(process.getInputStream(), true);
你的流阅读会一直阻塞你的代码。
您可能希望将已启动进程的输出重定向到日志文件并稍后阅读。
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();