read()阻塞如何工作?

时间:2017-03-17 10:23:24

标签: java sockets stream

有一段时间我一直在学习Java中的Streams和Sockets。每个人都说是read()块(特别是在网络比我们的计算机慢得多的插座中)。我试图想象它是如何工作的。我的意思是它看起来像:

(PSEUDOCODE)
read() {
    while (true) {
        if (there is at least one byte to read) {
            return this byte;
        }
    }
}

或者它与其他低级别的东西有什么关系?我假设Java中的Streams是用C / C ++实现的。我的问题是,首先read()如何工作,第二个我们的线程在读取时会得到任何类型的“睡眠”?我的意思是一段时间(真实)是CPU周期的浪费,我想知道在read()上阻塞的线程是否会被另一个线程通知“嘿,你的字节已经准备好了!”提前谢谢。

3 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

在我看来,就像System.in一样,当你使用它时,就像这个新的Scanner(System.in).nextInt()。主线程等待来自控制台的输入,睡眠。当你输入一些东西时,InputStream System.in获取数据并进入我们的程序。如果日期结束,你可以得到一个标志,并做一些事情来防止你的工作异常。如果它没有帮助,那么这里有新的,对不起:-D

答案 2 :(得分:0)

这是javadoc所说的:

  

从输入流中读取下一个数据字节。值字节是   返回为0到255范围内的int。如果没有可用的字节   因为已到达流的末尾,值为-1   回。此方法阻塞,直到输入数据可用,结束   检测到流,或抛出异常。

它表示它会阻止线程/调用,直到数据可用。根据线程生命周期,以下是真实的:

  

如果一个线程在阻塞方法中被阻止,它将保留在任何一个中   阻塞状态等待,阻止或TIMED_WAITING。

此外,挂起或阻塞的线程不会消耗任何CPU时间。因此,可以肯定地说这个块相当于在线程上调用wait()方法,并且一旦数据可用就会notify()'d(如果{{则线程不会释放锁/ CPU) 1}}被调用,但你不能通知一个睡眠线程,它排除了线程在sleep方法中进入sleep的可能性。)

Hereread方法的openjdk代码。由于它调用了read方法,因此并不完全清楚线程是如何被阻止的。但是,根据native vs sleep的文档和行为,我们可以说它进入wait状态并且不消耗CPU。