有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java取消一个选择键,但在以后重用它

我想先将一个通道注册到选择器,以便仅在connect only上执行select(),然后在write only上执行

大概是这样的:

SelectionKey key = server.register(selector, SelectionKey.OP_CONNECT);
server.connect(address);
int readyChannels = 0;
while (readyChannels == 0) readyChannels = selector.select(config.connectTimeout);
server.finishConnect();
key.cancel();

key = server.register(selector, SelectionKey.OP_WRITE);
// write something to the channel and check timeout 
// with selector.select(config.writeTimeout)

然而,当我到达代码中的第二个register(...)时,我得到一个CancelledKeyException

还有别的办法吗

正确的方法是每次定义一个新的选择器吗

另外,我知道我可以用key.isWritable()之类的


共 (1) 个答案

  1. # 1 楼答案

    1. 如果finishConnect()返回false,就不能像返回true那样继续

    2. 您的问题是,您没有在取消和注册之间调用选择器,因此存在未完成的任务。这里最简单的解决方案是删除cancel和register,直接调整现有选择键的顶部

    3. 然而,由于您只是在连接完成之前进行有效的阻塞,因此在阻塞模式下进行连接,然后在后续的I/O中转到非阻塞会更简单:

      // Still in blocking mode, no register() yet ...
      server.socket().connect(address, connectTimeout);
      server.configureBlocking(false);
      key = server.register(selector, SelectionKey.OP_WRITE);
      

      。。。请注意,如果超时过期,将引发异常

    实际上,我很少遇到在客户端以非阻塞模式使用NIO的情况