如何实现ProcessBuilder创建的Java进程间双向通信?
Java进程间通过标准流实现双向通信的正确方式
我通过ProcessBuilder在Main类中创建ProcessTest子进程,目前已实现通过BufferedReader读取子进程System.out输出的消息。现在需要实现Main向ProcessTest发送消息,我尝试用BufferedWriter写入p.getOutputStream(),但不确定该方案是否可行,也不清楚ProcessTest中如何接收消息,想请教通过重定向标准流实现进程间双向通信的正确方式。
原代码
public class Main { public static void main(String[] args) throws IOException, InterruptedException { ProcessBuilder pb = new ProcessBuilder("java", "com.company.ProcessTest"); pb.directory(new File("some path")); Process p = pb.start(); try (var reader = new BufferedReader( new InputStreamReader(p.getInputStream()))) { String line = null; while (true) { if (!reader.ready()) { Thread.sleep(500); } else { line = reader.readLine(); System.out.println(line); } } } } } public class ProcessTest { public static void main(String[] args) throws InterruptedException, IOException { System.out.println("Hello from ProcessTest"); } }
我尝试的发送代码片段
var writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream())); writer.write("Some message"); writer.newLine(); writer.flush();
解决方案
你的发送方案完全可行,Process.getOutputStream()对应的就是子进程的标准输入(System.in),写入这个流就能将消息传递给子进程。下面是完整的双向通信实现方式:
1. 修改Main类:多线程处理读写
由于读和写操作会互相阻塞,建议用单独线程处理子进程的输出读取,主线程负责发送消息:
import java.io.*; public class Main { public static void main(String[] args) throws IOException, InterruptedException { ProcessBuilder pb = new ProcessBuilder("java", "com.company.ProcessTest"); pb.directory(new File("你的类文件目录路径")); Process p = pb.start(); // 单独线程读取子进程输出 new Thread(() -> { try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println("子进程输出:" + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 主线程向子进程发送消息 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()))) { // 示例发送消息 writer.write("来自Main的消息1"); writer.newLine(); writer.flush(); Thread.sleep(2000); writer.write("来自Main的消息2"); writer.newLine(); writer.flush(); // 如果需要结束通信,可关闭输出流,子进程会收到EOF // writer.close(); } } }
2. 修改ProcessTest类:读取标准输入
直接通过System.in读取Main发送的消息,同样用BufferedReader处理:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ProcessTest { public static void main(String[] args) throws InterruptedException, IOException { System.out.println("Hello from ProcessTest"); // 读取Main发送的消息 try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { String line; while ((line = reader.readLine()) != null) { System.out.println("收到Main的消息:" + line); // 可以在这里添加回复逻辑 System.out.println("回复Main:已收到消息 - " + line); System.out.flush(); } } } }
关键注意事项
- 必须调用flush():BufferedWriter有缓冲区,不调用flush()消息会留在缓冲区,子进程无法立即收到。
- 处理EOF:当Main端关闭输出流时,子进程的readLine()会返回null,此时可以退出读取循环,避免无限阻塞。
- 多线程分离读写:单线程下如果一直等待读取子进程输出,会导致无法执行发送操作,反之亦然,用多线程可以避免这个问题。
- 目录路径正确:确保ProcessBuilder指定的目录是ProcessTest类文件所在的目录,或者使用完整的类路径执行命令。
内容的提问来源于stack exchange,提问作者Ваня Самохвалов
相关产品推荐
相关产品推荐

