【问题标题】:When exactly Blocking IO blocks?什么时候阻塞 IO 块?
【发布时间】:2019-09-04 06:38:58
【问题描述】:

InputStream.available() javadoc:

返回可以从中读取(或跳过)的字节数 此输入流无阻塞

  1. 我认为阻塞意味着我调用 read() 的线程被阻塞(控制流不会进一步),直到 read() 返回。从这个意义上说,我看不到任何可以在没有阻塞的情况下调用 read() 的场景。

  2. 阻塞的另一个含义可能是,如果我想读取 3 个字节并且没有或只有 1 个字节可用,read() 将阻塞并等待更多字节出现 - 但我无法理解方式 b/c 然后调用 read() 并尝试读取超过可用的内容可能会导致永久阻塞(只是从 10 个字节的文件中读取 100 个字节)。

java.io 在哪种意义上阻塞 (1) 或 (2)?

我无法模拟使用 FileInputStream 或 ByteArrayInputStream 读取 IO 块的方法(意义(2))时的情况:

        // file content is: 1 2 3       
        FileInputStream myStream = new FileInputStream("d:\\file.txt");
        byte[] b = new byte[100];
        myStream.read(b);
        System.out.println("control reached here?");
        System.out.println(Arrays.toString(b));

输出:

reached here?
[122, 100, 122, 120, 118, 122, 120, 32, 118, 122, 120, 118, 32, 122, 120, 118, 32, 122, 118, 99, 122, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

第二次调用 myStream.read(b) 也只会返回 -1 而不会阻塞。

在什么情况下会发生阻塞?

我认为如果我尝试读取 5 个字节并且有 3 个字节,就会发生这种情况。如果没有,则表示 EOF / end-of-stream 并返回 -1(也没有阻塞)。

附:我倾向于认为 java.io 既是 (1) 又是 (2):它是同步的 (1) 和阻塞的 (2),但实际上只有在使用套接字时才能观察到阻塞 (@987654329 @)。

【问题讨论】:

标签: java io blocking


【解决方案1】:

或多或少的选项 2,但您不必担心 read 会阻塞,即使已经有一些数据需要处理。

这里有一个提示:不要使用 available()。它实际上是无用的,它提供的信息并不能真正让你做你不能做的事情。

假设您有一个 TCP 网络连接。在您或对方挂断连接之前,可以通过线路发送多少字节是没有限制的,但另一方面,可能还有 10 个字节要读取,并且不会再有更多字节了有一段时间,因为发件人目前处于沉默状态。

假设你这样做:

byte[] b = new byte[100];
int r = in.read(b);

这里会发生什么,r 将变为 10b 中的前 10 个位置将被填满,仅此而已。 read 'smartly' 返回:如果有 0 个字节,它不会返回(读取保证它会阻塞,直到它读取至少 1 个字节,或者流关闭,在这种情况下它返回 -1)。 .. 如果有字节要读取,它会读取一个有效的块。

blocking,具体来说,意味着线程将被暂停并且不会恢复,直到发生变化。 (字节进来了,或者流被关闭了)。

【讨论】:

    【解决方案2】:

    场景2就是这个意思。

    (经过一些实验后更新)

    似乎本地磁盘文件I/O不被认为是阻塞的。对于 FileInputStream,available() 方法返回文件的剩余长度。也就是说,如果文件长 91764 字节,而你读取了 4 个字节,那么在此之后 available() 将返回 91760。

    我发现这个结果令人惊讶;如果您尝试读取这 91760 个字节,您的线程肯定会阻塞磁盘 I/O。

    对于网络套接字连接,结果更容易理解。未来可能从远程系统到达的数据量当然是未知的; available() 会告诉你有多少已经到达并且现在可以阅读。在这种情况下,“阻塞”将是无限期的——等待远程主机可以发送,这超出了 I/O 系统的知识范围。 at 留下 20 个字节可用于进一步读取而不会阻塞。

    【讨论】:

    • 异步 允许您同时做其他工作。非阻塞,如果它存在于文件中,它不存在,会立即成功或失败。
    • 你当然是对的。谢谢。无论如何,FWiW,我重写了我的答案。
    • 您不应说明availagle()FileInoutStreM 返回的内容。这正是 FIONREAD 在许多系统中发生的事情。它没有在任何地方指定,在 Java 中也没有在 ioctl() 的 AFAIK 中指定。可能 OP 正在读取网络文件。
    猜你喜欢
    • 1970-01-01
    • 2013-02-19
    • 2011-09-09
    • 2013-05-28
    • 2021-10-05
    • 2012-09-03
    • 2011-04-26
    • 2010-11-17
    • 1970-01-01
    相关资源
    最近更新 更多