猿问

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(),我也希望第一个事件的读取只会阻止第二个事件的读取,而不会擦除或消耗过多的流数据。为什么这样做会导致我的所有数据都无法显示?



慕村9548890
浏览 468回答 3
3回答

阿晨1998

某些实现的基础数据源InputStream可以表示已到达流的末尾,并且将不再发送任何数据。在接收到该信号之前,此类流的读取操作可能会阻塞。例如,InputStream来自Socket套接字的a 将阻止而不是返回EOF,直到接收到设置了FIN标志的TCP数据包。当从这样的流中接收到EOF时,可以确保已可靠地接收了在该套接字上发送的所有数据,并且您将无法再读取任何数据。(另一方面,如果阻塞读取导致异常,则可能丢失了一些数据。)其他流(例如来自原始文件或串行端口的流)可能缺少相似的格式或协议,以表明不再有可用数据。当当前没有可用数据时,此类流可以立即返回EOF(-1)而不是阻塞。但是,如果没有这种格式或协议,则无法确定另一端何时完成发送数据。关于您的第二个问题,听起来您可能患有比赛状况。没有看到有问题的代码,我猜测问题实际上出在您的“显示”方法上。可能第二个通知显示的尝试以某种方式掩盖了第一个通知期间所做的工作。

紫衣仙女

如果流结束,则返回-1。如果流仍处于打开状态(即套接字连接),但没有数据到达读取端(服务器速度很慢,网络速度很慢,...),则read()块。您不需要致电available()。我很难理解您的通知设计,但是除了read()本身之外,您不需要任何调用。这里的available()方法只是为了方便。
随时随地看视频慕课网APP

相关分类

Java
我要回答