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

如何同时读取InputStream并执行其他任务?

问题原因

你遇到的阻塞问题核心在于BufferedReader.lines().forEach()的特性:这个方法会一直读取输入流,直到流遇到**结束标记(EOF)**才会终止迭代。只要cmdsin流没被关闭,它就会一直阻塞等待数据,后面的代码自然无法执行。另外你每次循环都重复创建InputStreamReader和BufferedReader,这不仅浪费资源,还会导致流的状态混乱,完全没必要。

解决方案

要同时处理两个输入流且不阻塞后续代码,核心是让两个流的读取操作互不干扰,下面是两种可行方案:

方案1:多线程分离读取逻辑

把两个流的读取操作放到独立线程中,让它们并行运行,主线程可以正常执行其他代码,且不需要重复创建流读取器。

示例代码:

// 初始化流读取器,只需执行一次
BufferedReader cmdBr = new BufferedReader(new InputStreamReader(cmdsin, StandardCharsets.UTF_8));
BufferedReader dataBr = new BufferedReader(new InputStreamReader(datain, StandardCharsets.UTF_8));

// 启动CMD流读取线程
new Thread(() -> {
    String line;
    try {
        while ((line = cmdBr.readLine()) != null) {
            System.out.println("CMD: " + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            cmdBr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

// 启动DATA流读取线程
new Thread(() -> {
    String line;
    try {
        while ((line = dataBr.readLine()) != null) {
            System.out.println("DATA: " + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            dataBr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

// 主线程执行其他代码,不受读取操作阻塞
while (true) {
    System.out.println("其他业务代码执行中...");
    try {
        Thread.sleep(1000); // 示例:每秒执行一次
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
  • 注意:线程中必须处理IO异常,且在finally块关闭流,避免资源泄漏。如果需要线程间协作(比如流读取完毕后通知主线程),可以用CountDownLatch等同步工具。

方案2:单线程轮询(非阻塞检查)

如果不想使用多线程,可以用BufferedReader.ready()方法预先检查流是否有可读数据,有数据才读取,无数据则跳过,避免阻塞。

示例代码:

// 初始化读取器,只需一次
BufferedReader cmdBr = new BufferedReader(new InputStreamReader(cmdsin, StandardCharsets.UTF_8));
BufferedReader dataBr = new BufferedReader(new InputStreamReader(datain, StandardCharsets.UTF_8));

while (true) {
    // 检查并读取CMD流
    if (cmdBr.ready()) {
        String line = cmdBr.readLine();
        if (line != null) {
            System.out.println("CMD: " + line);
        }
    }

    // 检查并读取DATA流
    if (dataBr.ready()) {
        String line = dataBr.readLine();
        if (line != null) {
            System.out.println("DATA: " + line);
        }
    }

    // 执行其他代码
    System.out.println("其他业务代码执行中...");
    try {
        Thread.sleep(100); // 加延迟避免CPU空转
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
  • 注意:ready()仅能判断当前时刻是否有数据,无法保证后续读取绝对不阻塞,但大部分场景下足够使用;必须添加延迟,否则会导致CPU占用过高。
补充说明

lines().forEach()本质是基于阻塞式流迭代,只有流关闭才会停止,完全不适合你这种需要持续同时读取多个流的场景。换成readLine()循环可以更灵活地控制读取逻辑,配合多线程或轮询就能解决阻塞问题。

内容的提问来源于stack exchange,提问作者Glitch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:35:31