首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我在java.io.PipedInputStream中发现错误了吗?

我在java.io.PipedInputStream中发现错误了吗?
EN

Stack Overflow用户
提问于 2015-02-20 05:23:08
回答 1查看 3.2K关注 0票数 20

我不确定,但我非常确定我在Oracle Java实现(我可以证实受影响的1.7.0_67和1.8.0_31 )中发现了一个bug (或未记录的特性)。

The Symptom

当管道已满时,写入管道的等待时间可能比管道再次空闲所需的时间长一秒。这个问题的最小示例如下(我已经将此处显示的示例推送到a repository on GitHub):

private static void threadA() throws IOException, InterruptedException {
  logA("Filling pipe...");
  pos.write(new byte[5]);
  logA("Pipe full. Writing one more byte...");
  pos.write(0);
  logA("Done.");
}

private static void threadB() throws IOException, InterruptedException {
  logB("Sleeping a bit...");
  Thread.sleep(100);
  logB("Making space in pipe...");
  pis.read();
  logB("Done.");
}

pispos分别是连接的PipedInputStreamPipedOutputStream实例。logAlogB是辅助函数,它们输出线程名称(A或B)、以毫秒为单位的时间戳和消息。输出如下:

     0 A: Filling pipe...
     6 B: Sleeping a bit...
     7 A: Pipe full. Writing one more byte...
   108 B: Making space in pipe...
   109 B: Done.
  1009 A: Done.

可以看到,在B: DoneA: Done之间有一秒(1000毫秒)。这是由Oracle Java 1.7.0_67中的PipedInputStream实现引起的,如下所示:

private void awaitSpace() throws IOException {
    while (in == out) {
        checkStateForReceive();

        /* full: kick any waiting readers */
        notifyAll();
        try {
            wait(1000);
        } catch (InterruptedException ex) {
            throw new java.io.InterruptedIOException();
        }
    }
}

只有在超时(如上图所示的1000毫秒)或调用notifyAll()时,才会中断wait(1000),这只会在以下情况下发生:

awaitSpace()中的

  • ,在wait(1000)之前,正如我们在receivedLast()中的
  • 上面的代码片段中看到的,它在<代码>D26中的
  • 关闭时调用(在这里不适用),但是<代码>E127仅当<代码>E228E132正在等待空缓冲区填满<代码>E233时--也不适用于这里<代码>H234<代码>F235

Question

有没有人有足够的Java经验来告诉我这是否是预期的行为?PipedOutputStream.write(...)使用awaitSpace()方法来等待空闲空间,而他们的约定只是简单地声明:

此方法会阻塞,直到所有字节都写入输出流为止。

虽然严格来说没有违反这一点,但1秒的等待时间似乎相当长。如果我要解决这个问题(最小化/降低等待时间),我会建议在每次读取的末尾插入一个notifyAll(),以确保等待的写入者得到通知。为了避免额外的同步时间开销,可以使用简单的布尔标志(并且不会损害线程安全)。

影响的Java版本

到目前为止,我可以在Java 7和Java 8上验证这一点,准确地说是以下版本:

$ java -version
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

$ java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28617175

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档