Process
Java的Process进程,与线程不同,java的进程操作是极度依赖于操作系统的,通常我们在Java中有两种方式创建进程。
通过Runtime直接运行
Runtime.getRuntime().exec("...");
通过ProcessBuilder创建进程
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("");
Process process = processBuilder.start();
相比与Runtime创建,通过ProcessBuilder创建提供了更加方便的子进程输出输入流读写,个人更加推荐使用第二种创建进程。
JVM本身运行的java程序也是一个系统进程,在windows系统上,通过java程序创建的外部进程并没有自己的输出终端,其输出终端依赖于java进程。
在Linux和Mac系统上创建的外部进程并不是其java进程的子进程。
若想让它拥有其自己的输出终端,在Windows系统下我们使用以分离模式的方式启动此进程。
try {
Runtime.getRuntime().exec("cmd /c start ....");
} catch (IOException e) {
e.printStackTrace();
}
==踩坑,下面遇到的问题只是个人见解==
若不使用分离模式,则可能会遇到这种场景。
当子进程的标准输出被Java的Process标准输入流获取到的时候,若在缓冲区未得到及时的读取,则可能会因为数据过多的问题填满缓冲区,而导致子进程卡死。
如我在使用Java创建了一个外部媒体播放进程,但没有及时处理其InputStream中的数据,会使得外部进程卡死。
其它解决方案:
使用ProcessBuilder创建外部进程,并启动一个单独的线程,及时读取进程标准输入流中的数据
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("...");
try {
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
//保证连接到子进程的标准输出的标准输入流不被阻塞
InputStream inputStream = process.getInputStream();
while (inputStream.read() != -1){
//do nothing
}
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
});
//启动独立线程,不断循环处理
t1.start();
//主线程继续工作..
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com