我对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秒打印“无事件”。
但是当我尝试远程登录时,它开始非常快速地打印“无事件”。似乎select方法返回值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,选择方法返回1。
为什么?这是第二个问题。
第一次在这里提问。请原谅我的英语不好。
答案 0 :(得分:1)
您在select(long)中提供的数字与Thread.sleep(long)不同。根据:
https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html#select(long)
select是一项阻止操作,但只要能够选择频道,它就会继续进行。因此,当您连接时,它将不断循环并输出。您提供的long值是告诉select(long)方法何时放弃尝试选择一个通道,无论如何不要休眠线程。为了保证至少2秒钟的睡眠,您需要在循环结束之前添加Thread.sleep(2000)。
对于返回值,select()返回已更新的键的数量,可以为零。当您再次与telnet连接时,您将提供一个可以更新的新密钥。如果只有一个连接,则无需选择新的频道进行收听。因此,什么都不会切换。如果您有两个连接,则每次都修改其中一个是有意义的。