Java NIO select() 返回时没有选择键 - 为什么?

标签 java select nio

在编写一些测试代码时,我发现 Selector.select() 可以在没有 Selector.selectedKeys() 包含任何要处理的键的情况下返回。当我用

注册一个 accept()ed channel 时,这是在一个紧密的循环中发生的
SelectionKey.OP_READ | SelectionKey.OP_CONNECT

作为感兴趣的操作。

根据文档,select() 应该在以下情况下返回:

1) 有可以采取行动的 channel 。

2) 您显式调用 Selector.wakeup() - 未选择任何键。

3) 您显式地使用 Thread.interrupt() 执行 select() 的线程 - 没有选择键。

如果我在 select() 之后没有得到键,我一定是在情况 (2) 和 (3) 中。但是,我的代码没有调用 wakeup() 或 interrupt() 来启动这些返回。

关于导致此行为的原因有什么想法吗?

最佳答案

简短回答:从您对已接受连接感兴趣的操作列表中删除 OP_CONNECT - 已连接已接受连接。

我设法重现了这个问题,这可能正是您遇到的情况:

import java.net.*;
import java.nio.channels.*;


public class MyNioServer {
  public static void main(String[] params) throws Exception {
    final ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(true);
    serverChannel.socket().bind(new InetSocketAddress("localhost", 12345));
    System.out.println("Listening for incoming connections");
    final SocketChannel clientChannel = serverChannel.accept();
    System.out.println("Accepted connection: " + clientChannel);


    final Selector selector = Selector.open();
    clientChannel.configureBlocking(false);
    final SelectionKey clientKey = clientChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_CONNECT);
    System.out.println("Selecting...");
    System.out.println(selector.select());
    System.out.println(selector.selectedKeys().size());
    System.out.println(clientKey.readyOps());
  }
}

上述服务器收到连接后,连接上的第一个 select() 无阻塞退出,并且没有准备好操作的键。我不知道为什么 Java 会以这种方式运行,但似乎很多人都被这种行为所困扰。

在 Windows XP 上的 Sun JVM 1.5.0_06 以及 Linux 2.6 上的 Sun JVM 1.5.0_05 和 1.4.2_04 上的结果是相同的。

关于Java NIO select() 返回时没有选择键 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/204186/

相关文章:

java - 使用 java Files.walk 仅从根文件夹获取文件名并跳过其子目录时出现问题

java - 使用 Netty 实现 Servlet API

java - 在匿名或本地内部类中访问匿名或本地内部类

sql-server - SQL Server - 具有多个字段的 IN 子句

sql - 内部联接选择结果与表

mysql - 如何从 MySQL longblob 中选择文本数据

java - 针对小文件优化Java的NIO

java - 如何使用 illinois-edison 序列化/反序列化

java - 查找段落中的非 HTML 标记词

java - BufferedImage用作方法参数时变黑