java nio keyiterator.remove(),为什么要在java nio中的`selector.selectedKeys()。iterator()`中删除键?...

I found some sample code of java nio:

ServerSocketChannel server = ServerSocketChannel.open();

Selector selector = Selector.open();

server.socket().bind(new InetSocketAddress(8080));

server.configureBlocking(false);

server.register(selector, SelectionKey.OP_ACCEPT);

while(true) {

selector.select();

Iterator iter = selector.selectedKeys().iterator();

while (iter.hasNext()) {

SelectionKey key = (SelectionKey) iter.next();

iter.remove(); // Why remove it?

process(key);

}

}

When he gets the selected keys, he remove the key in the loop. Why we should do this?

UPDATE

Thanks to the answers provided by EJP and user270349, I think I understand it now, let me explain it in detail.

There are 2 tables in the selector:

registration table: when we call channel.register, there will be a new item(key) into it. Only if we call key.cancel(), it will be removed from this table.

ready for selection table: when we call selector.select(), the selector will look up the registration table, find the keys which are available, copy the references of them to this selection table. The items of this table won't be cleared by selector(that means, even if we call selector.select() again, it won't clear the existing items)

That's why we have to invoke iter.remove() when we got the key from selection table. If not, we will get the key again and again by selector.selectedKeys() even if it's not ready to use.

解决方案

Because the Selector never does that, it only adds to the set, so if you don't do it you will reprocess the event yourself next time the Selector returns.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java NIO,可以通过SelectionKey对象的interestOps()方法来监控Channel的状态。 首先,您需要创建一个Selector对象,并将其注册到您要监控的Channel上。然后,使用Selector.select()方法来阻塞等待已注册的Channel上发生事件。当有事件发生时,select()方法将返回,并返回一个SelectionKey集合,您可以通过这个集合来获取发生事件的Channel对象。接下来,您可以使用SelectionKey对象的interestOps()方法来检查Channel的状态。 例如,以下代码演示了如何使用Selector来监控Channel的可读状态: ``` Selector selector = Selector.open(); channel.register(selector, SelectionKey.OP_READ); while (true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isReadable()) { // Channel is ready for reading // Do something... } keyIterator.remove(); } } ``` 在这个示例,我们首先将Channel注册到Selector上,指定我们要监控Channel的可读状态。然后,在一个无限循环,我们使用Selector.select()方法等待Channel上发生事件,当有事件发生时,我们遍历SelectionKey集合,检查哪些Channel是可读的。 当我们发现可读的Channel时,我们可以在其执行读操作,并在操作完成后将SelectionKey从集合删除。这样,我们就可以在控制台监控Channel的状态了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值