Java非阻塞IO CPU泄漏

Java非阻塞IO CPU泄漏,java,asynchronous,cpu,nio,memory-leaks,Java,Asynchronous,Cpu,Nio,Memory Leaks,我编写了简单的NIO服务器: public static void main(String[] args) throws Exception { ByteBuffer buffer = ByteBuffer.allocateDirect(65536); Selector selector = Selector.open(); ServerSocketChannel server = ServerSocketChannel.open(); server.config

我编写了简单的NIO服务器:

public static void main(String[] args) throws Exception
{
    ByteBuffer buffer = ByteBuffer.allocateDirect(65536);
    Selector selector = Selector.open();
    ServerSocketChannel server = ServerSocketChannel.open();
    server.configureBlocking(false);
    server.bind(new InetSocketAddress(724));
    server.register(selector, SelectionKey.OP_ACCEPT);
    while(server.isOpen())
    {
        selector.selectNow();
        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
        while(iterator.hasNext())
        {
            SelectionKey key = iterator.next();
            iterator.remove();
            if(!key.isValid())
            {
                System.out.println("Invalid key removed!");
                key.channel().close();
                key.cancel();
                continue;
            }
            if(key.isAcceptable())
            {
                server.accept().configureBlocking(false).register(selector, SelectionKey.OP_READ);
                System.out.println("Accepting channel...");
                continue;
            }
            if(key.isReadable())
            {
                SocketChannel channel = (SocketChannel) key.channel();
                try
                {
                    channel.read((ByteBuffer) buffer.clear());
                    if(buffer.flip().limit() == 0)
                    {
                        continue;
                    }
                    System.out.println(buffer.get() & 0xFF);
                } catch(Exception e)
                {
                    e.printStackTrace();
                    channel.close();
                    key.cancel();
                }
            }
        }
    }
}
一旦客户机与服务器断开连接,CPU上的负载将增加40%

我试图找到一个解决办法,但搜索毫无结果。 我认为这是由于选择器没有删除断开客户机的连接,但我不知道如何测试客户机是否断开连接。channel.isOpen()始终返回true。

此方法执行非阻塞选择操作。如果自上一次选择操作以来没有通道可选择,则此方法立即返回零

是的,这会烧掉CPU;它是无阻塞的,你有一个紧密的循环


编辑添加:通常使用
选择器的想法是使用阻塞
select()
select(长超时)
版本,这意味着一旦套接字执行某项操作,它就会解除阻塞

找到了解决方案。收到EOS后,我忘记了关闭连接

if(channel.read((ByteBuffer) buffer.clear()) == -1)
{
    channel.close();
    continue;
}

你有没有试过用电脑分析?这可能会准确地告诉您系统在哪里花费时间。编辑:大多数CPU时间都是由java.net.SocketInputStream.read(byte[],int,int)花费的;如果刚刚关闭通道,则不需要取消键。Selector.select()也会发生同样的情况。我测试了Selector.select()和Selector.select(超时),结果相同。在哪里测试它们?你有什么不同的做法?使用
select()?我不知道怎么做differently@user1936245如果你不知道怎么做,你为什么说你已经做了?或者,如果你已经这样做了,为什么你说你不知道怎么做?这并没有关闭连接。它只是取消了钥匙。你应该关闭EOS上的连接,这是正确的,但你没有这样做。我重复一遍。关闭频道后,无需取消按键。给你修好了。
if(channel.read((ByteBuffer) buffer.clear()) == -1)
{
    channel.close();
    continue;
}