为什么当我尝试 telnet 时 select 方法 return 0 立即出现?

why does select method return 0 immediately when I try to telnet it?

我不熟悉 Java Nio。我试着写了一个像这样的小演示:

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress(9999)).configureBlocking(false);
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    for (; ; ) {
        int select = selector.select(2_000);
        if (select == 0) {
            System.out.println("no event");
            continue;
        }
        System.out.println("select = " + select);
   }

超时设置为 2 秒,程序每 2 秒打印一次 "no event"。

但是当我尝试远程登录它时它开始打印 "no event" 非常 fast.It 似乎 select 方法 returns 值 0 没有被阻止。

为什么?这是第一个问题。

当我尝试像这样在 for 循环中添加一些逻辑时:

for (; ; ) {
            int select = selector.select();
            if (select == 0) {
                System.out.println("no event");
                continue;
            }
            System.out.println("select = " + select);
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            System.out.println("iterator = " + iterator.hasNext());
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
            }
        }

然后我再次telnet它,select方法returns 1.

为什么?那就是第二个问题了。

第一次在这里提问。请原谅我糟糕的英语。

您在 select(long) 中提供的号码与 Thread.sleep(long) 不同。根据:

https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html#select(long)

select 是一个阻塞操作,但它会在能够 select 通道后立即进行。因此,当您连接时,它会不断循环和输出。您提供的 long 值是告诉 select(long) 方法何时放弃尝试 select 一个通道,而不是让线程休眠。为了保证至少 2 秒的休眠,您需要在循环结束前添加 Thread.sleep(2000)。

至于return值,select() returns更新的键数,可能为零。当您再次使用 telnet 连接时,您将提供一个可以更新的新密钥。如果您只有一个连接,则无需 select 一个新的频道来收听。因此,没有任何东西被切换。如果您有两个连接,那么每次都修改其中一个连接是有意义的。