Process.waitFor() 死锁问题了解和解决

ProcessBuilder pb = new ProcessBuilder("C:\Debug\TestRedis.exe", keyNmae);
pb.redirectErrorStream(true);
Process process = pb.start();
//可能导致进程阻塞,甚至死锁
int ret = process.waitFor();

1、waitFor问题描述分析

1、 主进程中调用pb.start会创建一个子进程,用于执行shell /exe 脚本。子进程创建后会和主进程分别独立运行。
2.、因为主进程需要等待脚本执行完成,然后对脚本返回值或输出进行处理,所以这里主进程调用process.waitFor()等待子进程完成。

3.、进程执行过程就是不断的打印信息。主进程中可以通过Process.getInputStream和Process.getErrorStream获取并处理。
4.、这时候子进程不断向主进程发生数据,而主进程调用Process.waitfor后已挂起。当前子进程和主进程之间的缓冲区塞满后进程不能继续写数据,然后也会挂起
5.、这样子进程等待主进程读取数据,主进程等待子进程结束,两个进程相互等待,最终导致死锁。

2、解决死锁问题

基于上述分析,只要主进程在waitFor之前,能不断处理缓冲区中的数据就可以。因为,我们可以再waitfor之前,单独启2个额外的线程,分别用于处理InputStream和ErrorStream就可以

                try (
                        InputStream inputStream = process.getInputStream();
                        InputStream inputErrorStream = process.getErrorStream();
                ) {
                    // 读取Shell的输出内容,并添加到string中:
                    //启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流
                    new Thread(() -> {
                        try {
                            val msg = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
                            response.setShellOutput(msg);
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        }
                    }).start();

                    new Thread(() -> {
                        try {
                            var errMsg = IOUtils.toString(inputErrorStream, StandardCharsets.UTF_8);
                            response.setShellErrorOutput(errMsg);
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        }
                    }).start();

                    process.waitFor(2, TimeUnit.HOURS);////可能导致进程阻塞,甚至死锁
                    int exitCode = process.exitValue();//
                    response.setSuccessful(exitCode == SHELL_EXIT_CODE_SUCCESS);
                }
原文地址:https://www.cnblogs.com/muzhongjiang/p/13390606.html