什么时候java nio选择器在select()调用时取消阻塞

时间:2011-05-14 22:26:53

标签: java nio

我正在学习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并唤醒选择器。 这是导致选择器选择此频道的原因吗?那么我们用这种方式发出信号来选择频道吗?

现在假设写入套接字通道选择器时通过更改来指示 感兴趣的是频道可以写入。 但是假设在写入没有完成由于套接字缓冲区已满,如代码所示,那么我们不会改变兴趣并将其保持为只写。 然后选择器何时选择此频道?

2 个答案:

答案 0 :(得分:3)

  1. this.accept(key)调用serverSocketChannel.accept(),返回套接字通道,以便与客户端进行通信。 频道已在选择器中注册“读取”操作,即选择器现在具有两个注册:

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

答案 1 :(得分:1)

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

NB获得零长度write()结果是使用OP_WRITE的唯一场合。大部分时间都有空间,因此OP_WRITE将继续触发。你不希望这样,所以你通常没有为一个频道注册OP_WRITE:只有当它刚从write返回0时;并且当通过在OP_WRITE之后重新触发该写入最终完成时取消注册它。