You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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,提问作者Ваня Самохвалов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:10:24