Java InputStream 阻塞读取

2022-08-31 17:17:59

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

如果由于已到达流的末尾而没有可用的字节,则返回值 -1。此方法将阻止,直到输入数据可用、检测到流的末尾或引发异常。

我有一个循环在做读取,当流中没有发送任何内容时,我总是得到-1。这是意料之中的。while(true)

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

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


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

我最终更改了我的代码,以便当我获得一个我称之为存储字节的事件时。现在它工作正常,我的所有数据都显示出来了。if(inputStream.available() > 0) while((aByte = read()) > -1)

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


答案 1

某些实现的基础数据源可以发出信号,表明已到达流的末尾,并且不会再发送更多数据。在接收到此信号之前,对此类流的读取操作可能会阻塞。InputStream

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

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


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


答案 2

如果它是流结束,则返回 -1。如果流仍然打开(即套接字连接),但没有数据到达读取端(服务器速度慢,网络速度慢,...),则read()块。

你不需要调用可用()。我很难理解你的通知设计,但你不需要任何调用,除了read()本身。可用的方法()只是为了方便起见。


推荐