【问题标题】:when does java nio selector unblock on select() calljava nio 选择器何时在 select() 调用上解除阻塞
【发布时间】:2011-05-16 14:11:31
【问题描述】:

我正在学习 NIO 包。我参考了here 中的 NioServer 示例。 NioServer.java 中的选择器线程阻塞

this.selector.select(); 
Iterator<SelectionKey> selectedKeys = this.selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
    SelectionKey key = selectedKeys.next();
    selectedKeys.remove();
    if (!key.isValid()) {
        continue;
    }

    if (key.isAcceptable()) {
        this.accept(key);
    } else if (key.isReadable()) {
        this.read(key);
    } else if (key.isWritable()) {
        this.write(key);
    }

当远程客户端连接时,this.accept(key) 被调用,在这个方法中兴趣 interestOps 更改为 Read 并唤醒选择器。 这是导致选择器选择此频道的原因吗?所以我们以这种方式发出信号来选择要选择的频道?

现在假设写入套接字通道选择器是通过更改 对通道已准备好写入感兴趣。 但是假设由于套接字缓冲区已满而导致写入未完成,如代码所示,那么我们不改变兴趣并保持其为只写。 那么选择器什么时候会选择这个频道呢?

【问题讨论】:

  • 应避免无限期阻塞,而应使用重载的 select(long timeout) 方法。

标签: java nio


【解决方案1】:
  1. this.accept(key) 调用 serverSocketChannel.accept(),它返回一个 new 套接字通道用于与客户端通信。 this 通道向选择器注册了“读取”操作,即选择器现在有 两个 注册:

    • 原来的ServerSocketChannel,带有OP_ACCEPT
    • 新客户端的 SocketChannel,带有 OP_READ
  2. 如果由于缓冲区已满而无法完成写入,则相应的 SocketChannel 将保持注册到 OP_WRITE。一旦客户端从另一端读取了一些数据,将再次选择通道,允许我们在将兴趣集翻转回 OP_READ 之前写入剩余的数据。

【讨论】:

    【解决方案2】:

    当套接字发送缓冲区中有空间时触发OP_WRITE。

    NB 获得零长度 write() 结果是使用 OP_WRITE 的唯一场合。大多数时候都有空间,所以 OP_WRITE 会一直触发。您不希望这样,因此您通常没有为通道注册 OP_WRITE:仅当它刚刚从写入返回零时;当写入最终通过在 OP_WRITE 之后重新触发完成时,您取消注册它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      • 2013-12-28
      相关资源
      最近更新 更多