ProcessBuilder进程线程因大stdin流挂起问题排查求助
ProcessBuilder 处理大输入时线程挂起的原因及解决方法
问题根源:管道缓冲区死锁
当你向子进程的stdin写入大量数据后直接读取stdout,会触发进程间管道死锁,核心原因是操作系统为管道分配的缓冲区容量有限:
- 子进程
cat会将从stdin读取的数据写入stdout,当stdout的缓冲区被填满时,子进程会阻塞,无法继续读取stdin的剩余数据。 - 父进程此时已写完
stdin并关闭输出流,但卡在stdout.readAllBytes()等待子进程输出;而子进程因stdout阻塞无法继续执行,最终双方互相等待,导致线程挂起。
解决方案:并发处理IO操作
需要用独立线程处理stdin的写入,让父进程可以同时读取stdout,避免缓冲区满导致的阻塞。修正后的代码示例:
ProcessBuilder builder = new ProcessBuilder(); builder.command("cat"); Process process = builder.start(); // 启动单独线程写入stdin,与主线程的读操作并发执行 new Thread(() -> { try (BufferedOutputStream outputStream = new BufferedOutputStream(process.getOutputStream())) { outputStream.write(data); } catch (IOException e) { e.printStackTrace(); } }).start(); // 主线程读取stdout try (InputStream stdout = process.getInputStream()) { byte[] out = stdout.readAllBytes(); // 此处处理输出数据 } catch (IOException e) { e.printStackTrace(); } // 等待子进程完全结束,避免资源泄漏 int exitCode = process.waitFor();
关键注意事项
- 始终使用
try-with-resources语法自动关闭流,确保IO资源被正确释放。 - 必须等待子进程结束(
process.waitFor()),避免父进程提前退出导致子进程成为僵尸进程。
内容的提问来源于stack exchange,提问作者Henrik
相关产品推荐
相关产品推荐

