Java非阻塞IO CPU泄漏
我编写了简单的NIO服务器: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
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;
}