【问题标题】:Wrapping InputStream to non blocking ReadableByteChannel将 InputStream 包装到非阻塞 ReadableByteChannel
【发布时间】:2014-10-07 07:33:31
【问题描述】:

是否可以从 InputStream 对象创建非阻塞 ReadableByteChannel?

Channel.newChannel(inputStream) - 生成可能被阻塞的 InputStream.read 调用阻塞的通道

【问题讨论】:

    标签: java nio


    【解决方案1】:

    不,这是不可能的。请参阅Javadoc

    【讨论】:

    • 但也许有些库存在?
    • 不,这是不可能的,请参阅 Javadoc。没有图书馆可以让不可能的事情成为可能。
    • @downvoter 不要自欺欺人。如果您真的认为相反,请发布您自己的答案,说明如何发表评论、投票等。
    • 有可能,只是不建议。可以以Thread 为代价将阻塞输入通过管道传输到非阻塞通道,但显然这会破坏非阻塞 io 的激励目的(即避免线程)。
    【解决方案2】:

    您可以尝试自己实现这样的通道,使用“Inputstream.avalable()”来避免阻塞。但是,这种方法并不能保证返回正确的值,所以你必须检查你使用的 Inputstream 实现。

    您确定需要非阻塞通道吗?通常,它需要定期轮询以检查数据的到达。在数据到达时调用回调的异步通道更有意义。

    【讨论】:

      【解决方案3】:

      ReadableByteChannel.newChannel 方法

      public static ReadableByteChannel newChannel(final InputStream in) {
          checkNotNull(in, "in");
      
          if (in instanceof FileInputStream &&
              FileInputStream.class.equals(in.getClass())) {
              return ((FileInputStream)in).getChannel();
          }
      
          return new ReadableByteChannelImpl(in);
      }
      

      以及ReadableByteChannelImpl的读取方法

      public int read(ByteBuffer dst) throws IOException {
          int len = dst.remaining();
          int totalRead = 0;
          int bytesRead = 0;
          synchronized (readLock) {
              while (totalRead < len) {
                  int bytesToRead = Math.min((len - totalRead),
                                             TRANSFER_SIZE);
                  if (buf.length < bytesToRead)
                      buf = new byte[bytesToRead];
                  if ((totalRead > 0) && !(in.available() > 0))
                      break; // block at most once
                  try {
                      begin();
                      bytesRead = in.read(buf, 0, bytesToRead);
                  } finally {
                      end(bytesRead > 0);
                  }
                  if (bytesRead < 0)
                      break;
                  else
                      totalRead += bytesRead;
                  dst.put(buf, 0, bytesRead);
              }
              if ((bytesRead < 0) && (totalRead == 0))
                  return -1;
      
              return totalRead;
          }
      }
      

      所以,它只是调用了InputStream的read方法,以及InputStream的read方法的javadoc:

      此方法阻塞,直到输入数据可用,文件结尾是 检测到,或者抛出异常。

      因此您可以实现 InputStream 的子类并覆盖读取方法,并将这些方法实现为非阻塞。

      【讨论】:

      • '将方法实现为非阻塞'如何?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-22
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      相关资源
      最近更新 更多