如何同时读取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
相关产品推荐
相关产品推荐

