我的Java NIO选择器是使用select()实现的,因此它会阻塞直到发生以下情况之一:
即使多次调用
简化代码:
为什么
编辑:
将此更改为:
解决了问题。在某些情况下,代码会在
选定的键集可以提供一个fail-fast迭代器。 fail-fast迭代器检测到这种修改并在下一次迭代时抛出ConcurrentModificationException。因此,在foreach中修改集合或者冒着不确定的行为或者可能引起异常-具体取决于迭代器的实现。
解决方案:不要使用foreach。使用迭代器,并通过iterator.remove()删除键。
- 已注册的通道准备就绪
- 它被wakeup()唤醒
- 线程被中断
select()
返回0的情况做出了一些假设:
- 必须是第2或第3种情况。
- selectedKeys()应返回一个空的
ResultSet
- 我不需要调用
selectedKeys()
,可以继续下一个循环迭代,在其中将调用select()
。
select()
返回了0。如预期,selectedKeys()
返回一个包含1个SelectionKey
的Set
。即使多次调用
select()
,直到处理通道并移除SelectionKey
之前,它仍然总是返回0。这种情况基本上会陷入无限循环,因为select()
不会阻塞,而是总是立即返回0。简化代码:
Selector selector = Selector.open();
SocketChannel channel;
for (...) { // for each node
// Create and connect channels...
...
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ, someRelatedObject);
}
int ready;
Set<SelectionKey> readyKeys;
while (true) {
ready = selector.select();
readyKeys = selector.selectedKeys();
System.out.println("Ready channels: " + ready);
System.out.println("Selected channels: " + readyKeys.size());
if (ready == 0) {
continue;
}
for (SelectionKey key : readyKeys) {
if (key.isValid() && key.isReadable()) {
// Take action...
}
readyKeys.remove(key);
}
}
为什么
select()
会返回0,即使有一个准备好的通道?应该如何处理?编辑:
将此更改为:
for (SelectionKey key : readyKeys) {
if (key.isValid() && key.isReadable()) {
// Take action...
}
readyKeys.remove(key);
}
到这里
for (SelectionKey key : readyKeys) {
readyKeys.remove(key);
if (key.isValid() && key.isReadable()) {
// Take action...
}
}
解决了问题。在某些情况下,代码会在
remove()
删除键之前继续for
循环。
编辑2:
我最近才学到我的选定键集上的foreach循环是错误的。foreach使用集合的迭代器。在迭代过程中直接修改集合(而不是通过迭代器的方法)可能导致“任意,不确定”的行为。选定的键集可以提供一个fail-fast迭代器。 fail-fast迭代器检测到这种修改并在下一次迭代时抛出ConcurrentModificationException。因此,在foreach中修改集合或者冒着不确定的行为或者可能引起异常-具体取决于迭代器的实现。
解决方案:不要使用foreach。使用迭代器,并通过iterator.remove()删除键。
Iterator<SelectionKey> iterator;
SelectionKey key;
while (true) {
// ...
iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
key = iterator.next();
iterator.remove();
// ...
}
}
select()
返回0,尽管有准备好的通道?” - user207421iterator.remove()
立即删除每个SelectionKey
的优势是什么? - riha