何时恰好阻塞IO块?

时间:2019-04-13 20:25:06

标签: java io blocking

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 /流结束,并返回-1(也不会阻塞)。

P.S。我倾向于认为 java.io既是(1)又是(2):它既是同步的(1)又是阻塞的(2),但是实际上只有在使用套接字的情况下才观察到阻塞({{ 1}})。

2 个答案:

答案 0 :(得分:1)

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

提示:不要使用available()。它实际上是无用的,它所授予的信息并不能真正让您完成您原本无法做到的事情。

假设您有一个TCP网络连接。在您或另一端挂断连接之前,对可以跨行发送多少字节没有限制,但是在另一面,有可能剩下10个字节要读取,并且以后将不再发送有一阵子是因为发件人现在暂时保持沉默。

假设您然后执行此操作:

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

这里将要发生的是,r将为10b中的前10个插槽将被填充,仅此而已。 read“聪明”地返回:如果有0个字节,则不返回(读保证它会阻塞,直到它读取至少1个字节或关闭流,在这种情况下,它返回{{1 }})...,如果有要读取的字节,它将读取其中的有效块。

-1尤其是意味着该线程将被暂停,并且直到发生更改后才恢复。 (字节进入,或流关闭)。

答案 1 :(得分:0)

场景2就是这个意思。

(经过一些实验后更新)

似乎本地磁盘文件I / O不被视为阻塞。对于FileInputStream,available()方法返回文件的剩余长度。也就是说,如果文件的长度为91764字节,并且您读取了4个字节,则该available()将返回91760。

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

对于网络套接字连接,结果更易于理解。当然,将来可能从远程系统到达的数据量是未知的。 available()会告诉您有多少已经到达,现在可以读取。在这种情况下,“阻塞”将具有不确定的持续时间-等待直到远程主机可以发送为止,这超出了I / O系统的知识。 at留下20个字节可用于进一步读取而不会阻塞。