1

有非阻塞服务器,现在看起来像:

ServerSocketChannel server = ServerSocketChannel.open();
// ... Many stuff like initialise selector, load world, etc
while(server.isOpen())
{
    selector.select();
    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
    while(iterator.hasNext())
    {
        SelectionKey key = iterator.next();
        switch(key.interestOps())
        {
            case SelectionKey.OP_ACCEPT:
                // .... Accepting, register selector, packet handler etc
                break;
            case SelectionKey.OP_READ:
                // .... Read-write stuff
                break;
        }
        iterator.remove();
    }
}

我需要例如 1 个线程处理 100 个连接。其他 100 个连接处理另一个线程。我试着用这段代码做到这一点:

public class ConnectionsHandler implements Runnable
{
    private Selector selector;// For each thread gets its own selector

    @Override public void run()
    {
        while(Server.server.isOpen())
        {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext())
            {
                SelectionKey key = iterator.next();
                // .... Read-write stuff
                iterator.remove()
            }
        }
    }
}

但是第一次接受连接后的两个线程都冻结了......没有抛出任何异常,它只是冻结了。

4

1 回答 1

1

register() 是阻塞操作,select() 也是。如果 getMostFreeSelector() 返回另一个选择器并且它当时在 select() 中,则 register() 将阻塞,直到选择器唤醒。你可以调用 selector.wakeup() 来解决这个问题,或者总是注册到当前的选择器,但我会质疑整个架构。除非您有数千个连接,否则第二个选择器和线程几乎没有意义。

还要注意我上面关于 switch 语句的评论。

于 2013-08-04T22:37:26.997 回答