为什么Java nio消耗太多的CPU?



我用Java nio开发了一台服务器。并且建立了很少的连接(60-70(。虽然只建立了连接,没有数据流,但它消耗了我 30% 的 CPU(i7 第 8 代 12 核(。在数据流的情况下,它是 80-90%。当我使用 jvisualvm 分析程序时,似乎只使用了 selector.select(( 方法。我想知道该怎么做才能减少 CPU 使用率。

private void startServer() throws IOException {
this.selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
// retrieve server socket and bind to port
listenAddress = new InetSocketAddress("localhost", 8090);
serverChannel.socket().bind(listenAddress);
serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);
System.out.println("Server started...");
while (true) {
// wait for events
this.selector.select();
//work on selected keys
Iterator keys = this.selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
// this is necessary to prevent the same key from coming up 
// again the next time around.
keys.remove();
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
this.accept(key);
}
else if (key.isReadable()) {
this.read(key);
}
else if (key.isWritable()) {
this.write(key);
}
else if (key.isConnectable()) {
this.connect(key);
}
}
}
}

private void accept(SelectionKey key) throws IOException {
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
// register channel with selector for further IO
dataMapper.put(channel, new ArrayList());
channel.register(this.selector, SelectionKey.OP_READ);
}
//read from the socket channel
private void read(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int numRead = -1;
numRead = channel.read(buffer);
if (numRead == -1) {
this.dataMapper.remove(channel);
channel.close();
key.cancel();
return;
}
processBuffer(buffer);
}
public void startClient() throws IOException, InterruptedException {
String remoteHost = "localhost";
int remotePort = 8090
SocketChannel client = SocketChannel.open();
client.configureBlocking(false);
client.bind(new InitSocketAddress(0);
client.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
client.connect(new InetSocketAddress(remoteHost, remotePort));
client.register(this.selector, SelectionKey.OP_CONNECT);
}
public void connect(SelectionKey key){
SelectableChannel channel = key.channel();
SocketChannel socketChannel = (SocketChannel) channel;
boolean isConnected = socketChannel.finishConnect();
if(!isConnected)
System.out.println("Not Connectted!");
}
public void write(SelectionKey key){
SocketChannel socketChannel = (SocketChannel) channel;
ByteByffer buffer = getBuffer();
while(buf.remaining()>0){
socketChannel.write(buf)
}
//we wrote the data, now we interested in waiting for data.
key.interestOps(SelectionKey.OP_READ);
}

如果您的 select(( 返回 0,则可能会发生这种情况。 您可以打印一些日志来检查这一点。

请注意,您应该在连接后取消注册OP_CONNECT。

最新更新