Java InputStream 阻塞读取

新手上路,请多包涵

根据 java api, InputStream.read() 被描述为:

如果因为已到达流的末尾而没有可用字节,则返回值 -1。此方法会阻塞,直到输入数据可用、检测到流结束或抛出异常为止。

我有一个 while(true) 循环进行读取,当没有通过流发送任何内容时,我总是得到 -1。这是预期的。

我的问题是 read() 什么时候会阻塞?因为如果它没有获得任何数据,它会返回 -1。我希望阻塞读取要等到收到数据。如果您已经到达输入流的末尾,read() 不应该只是等待数据而不是返回 -1 吗?

或者 read() 是否仅在有另一个线程访问该流而您的 read() 无法访问该流时才阻塞?


这引出了我的下一个问题。我曾经有事件侦听器(由我的图书馆提供),它会在数据可用时通知我。当我收到通知时,我会调用 while((aByte = read()) > -1) 存储字节。当我在非常接近的时间收到两个事件并且没有显示我的所有数据时,我感到很困惑。似乎只显示第二个事件数据的尾端,其余的都不见了。

我最终更改了我的代码,以便在我收到一个事件时调用 if(inputStream.available() > 0) while((aByte = read()) > -1) 存储字节。现在它工作正常并且显示了我的所有数据。

有人可以解释这种行为吗? InputStream.available() 据说返回在阻止下一个调用者(流的?)之前可以读取的字节数。即使我不使用 .available() 我也希望第一个事件的读取只是阻止第二个事件的读取,而不是擦除或消耗太多的流数据。为什么这样做会导致无法显示我的所有数据?

原文由 jbu 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
1 个回答

InputStream 的一些实现的底层数据源可以发出信号,表明已经到达流的末尾,不再发送数据。在收到此信号之前,对此类流的读取操作可能会阻塞。

例如,来自 InputStreamSocket 套接字将阻塞,而不是返回 EOF,直到收到设置了 FIN 标志的 TCP 数据包。当从这样的流中接收到 EOF 时,您可以确信在该套接字上发送的所有数据都已可靠地接收到,并且您将无法再读取任何数据。 (另一方面,如果阻塞读取导致异常,一些数据可能已经丢失。)

其他流,如来自原始文件或串行端口的流,可能缺少类似的格式或协议来指示没有更多数据可用。这样的流可以立即返回 EOF (-1) 而不是在当前没有可用数据时阻塞。但是,如果没有这样的格式或协议,您就无法确定对方何时完成发送数据。


关于你的第二个问题,听起来你可能有比赛条件。没有看到有问题的代码,我猜问题实际上出在你的“显示”方法上。也许第二次通知显示的尝试以某种方式破坏了第一次通知期间完成的工作。

原文由 erickson 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题