【问题标题】:How does read() blocking works?read() 阻塞是如何工作的?
【发布时间】:2017-03-17 10:23:23
【问题描述】:

一段时间以来,我一直在研究 Java 中的流和套接字。每个人都说 read() 阻塞(尤其是在网络比我们的计算机慢得多的套接字中)。我试图想象这是如何工作的。我的意思是它看起来像:

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

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

【问题讨论】:

  • InputStream 类文档指定每个子类都为read() 方法提供自己的实现。如果您查看实现,您会发现通常会调用处理它的本机方法。我认为这与低级操作系统功能在处理此类操作时更有效的事实有关。
  • 我认为使用while(true){} 的那种忙等待是非常低效的,并且应该有一个异步通知系统来在数据可用时发出信号。
  • 线程未处于“睡眠”状态,它被阻塞等待 IO,只有在解除阻塞后才能再次调度。不会有旋转等待。所有这些都由(主要是本机)JVM 代码处理。

标签: java sockets stream


【解决方案1】:

javadoc 是这么说的:

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

它说它阻塞线程/调用,直到数据可用。根据线程生命周期,以下是正确的:

如果线程在阻塞方法中被阻塞,它会保留在任何 阻塞状态,例如WAITING、BLOCKED 或 TIMED_WAITING。

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

Hereread 方法的 openjdk 代码。当它调用native 方法时,并不完全清楚线程是如何被阻塞的。但是,根据sleepwait 的文档和行为,我们可以说它进入WAITING 状态并且不消耗CPU。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答,但您的回答大约涵盖了我问题的一半。如果你能更具体地回答我的问题。我真的很感激。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-23
      • 1970-01-01
      • 2015-12-08
      • 2012-04-22
      • 1970-01-01
      • 2018-09-10
      相关资源
      最近更新 更多