Java非阻塞IO CPU泄漏

时间:2022-05-23 21:46:13

I written simple NIO server:

我写了简单的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();
                }
            }
        }
    }
}

And it's client:

它是客户:

public static void main(String[] args) throws Exception
{
    try(Socket socket = new Socket("localhost", 724))
    {
        OutputStream output = socket.getOutputStream();
        output.write(15);
        output.flush();
    }
}

Once the client is disconnected from the server, the load on the CPU increases up to 40% Java非阻塞IO CPU泄漏

一旦客户端与服务器断开连接,CPU上的负载就会增加到40%

I tried to find a solution, but the search has given nothing. I think this is due to the fact that the selector does not remove disconnect the client, but I do not know how to test - whether the client is disconnected or not. channel.isOpen() always returns true.

我试图找到一个解决方案,但搜索没有给出任何结果。我认为这是因为选择器没有删除断开客户端,但我不知道如何测试 - 客户端是否断开连接。 channel.isOpen()始终返回true。

2 个解决方案

#1


2  

From the Javadoc for Selector.selectNow()

从Javadoc for Selector.selectNow()

This method performs a non-blocking selection operation. If no channels have become selectable since the previous selection operation then this method immediately returns zero.

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

Yes, that's going to burn CPU; it's non-blocking and you have a tight loop.

是的,这会烧掉CPU;它是非阻塞的,你有一个紧凑的循环。

Edit to add: Generally the idea behind using a Selector is that you use the blocking select() or select(long timeout) versions which means as soon as a socket does something, it unblocks.

编辑添加:通常使用Selector背后的想法是你使用阻塞select()或select(长超时)版本,这意味着一旦套接字执行某些操作,它就会解锁。

#2


0  

Found solution. I forgot close connection after EOS received.

找到解决方案EOS收到后我忘记了密切连接。

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

#1


2  

From the Javadoc for Selector.selectNow()

从Javadoc for Selector.selectNow()

This method performs a non-blocking selection operation. If no channels have become selectable since the previous selection operation then this method immediately returns zero.

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

Yes, that's going to burn CPU; it's non-blocking and you have a tight loop.

是的,这会烧掉CPU;它是非阻塞的,你有一个紧凑的循环。

Edit to add: Generally the idea behind using a Selector is that you use the blocking select() or select(long timeout) versions which means as soon as a socket does something, it unblocks.

编辑添加:通常使用Selector背后的想法是你使用阻塞select()或select(长超时)版本,这意味着一旦套接字执行某些操作,它就会解锁。

#2


0  

Found solution. I forgot close connection after EOS received.

找到解决方案EOS收到后我忘记了密切连接。

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

相关文章