Java nio选择器返回选中的键,但这些键上没有可用的操作



我正在尝试使用java nio类在java中编写套接字服务器。只使用非阻塞io,不使用异步io。

我有一个线程调用选择器的select()方法。最初,选择列表中唯一的通道是ServerSocketChannel。每次select()返回时,我枚举selectedKeys()列表并将io委托给单独的io线程。在将信息发送到io线程之前,我首先尝试通过将interestOps设置为零来关闭通道上的兴趣。这样做是为了使select()不再在该通道上触发,因为它应该继续触发,直到执行io。顺便说一下,您不能通过SelectionKey的cancel()方法完成此操作,因为这会将通道置于取消列表中,并且无法将其添加回选择列表。Cancel()仅用于在使用完通道后从列表中删除通道。我根本没有使用cancel(),因为关闭socket()会自动调用cancel()。

当io线程完成io时,它会返回给select线程,要求它关闭套接字或将interestOps重置为应有的值。

虽然这似乎有点工作,但我注意到select()似乎不断返回套接字通道,即使没有字节可读。顺便说一下,服务器只从套接字读取数据,并且只将兴趣设置为OP_READ(当我想关闭通道时为零)。为了测试一个特定的场景,我编写了一个客户端,它打开一个套接字,向它写入1k字节,休眠10秒,然后再向它写入1k字节,然后关闭套接字。在此睡眠期间,select()调用连续返回,当我读取套接字时,返回零字节。显然,当没有工作要做时,我不希望select()循环连续触发,因为我将固定CPU。我已经为非阻塞io设置了通道。我还应该提到,类似于下面引用的一个线程,此行为直到客户端打开套接字并开始发送数据时才会发生。在这种情况下,我仍然有服务器套接字通道,我正在监听OP_ACCEPT,并且select()调用不会为此不断触发。

下面是两个相似但不同的线程:

有选择器的无限循环's客户端没有连接

Java选择器在写入通道

后返回带有OP_READ的无数据的无限循环SelectionKey

这两个线程中的一些注释讨论了处理EOF,在read()时-1的情况。这不是我遇到的问题,所以请不要将此标记为那些的副本。

此外,在其中一个线程中,听起来像是有人建议,由于套接字通道处于非阻塞模式,无论是否有数据要读取,select()都将连续触发。这听起来很奇怪。我很难相信这是它应该的工作方式。我相信,当我表明我有兴趣在通道上读取时,select()应该只在有数据要读取时才返回所选列表中的该通道。

谢谢,尼克

听起来好像在迭代时没有从选定键集中删除选定键。在你链接的线程中有几个正确的例子。

NB其中一个声明如果没有事件,select()无限循环。只有当超时值为正时才会发生这种情况:它将超时并反复返回零。如果没有超时,它将无限阻塞。

NB cancel()实际上并不阻止您将通道添加回选择列表。您必须重新注册通道,如果select()没有在取消和重新注册之间执行(因为它可能没有处理其内部取消列表),则可能存在问题。但是你现在做这件事的方式并没有错。

相关内容

最新更新