select()与selectNow()时的java nio cpu使用问题
我尝试过使用select()和selectNow(),不同之处在于如果使用selectNow(),cpu使用率很高,我知道select()和selectNow()是阻塞操作还是非阻塞操作,那么如何解决这个问题呢?是JDK8中的bug吗?还是我的代码错误select()与selectNow()时的java nio cpu使用问题,java,jvm,selector,nio,Java,Jvm,Selector,Nio,我尝试过使用select()和selectNow(),不同之处在于如果使用selectNow(),cpu使用率很高,我知道select()和selectNow()是阻塞操作还是非阻塞操作,那么如何解决这个问题呢?是JDK8中的bug吗?还是我的代码错误 public static void main(String args[]) throws IOException { Selector selector = Selector.open(); ServerSocketChanne
public static void main(String args[]) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(9001));
channel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("The server listened at " + LocalDateTime.now() + " on port 9001");
Iterator<SelectionKey> iterator;
SelectionKey key;
while (true) {
selector.select(); << ---- Here is the key make CPU usage!
iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
String address = (new StringBuilder(sc.socket().getInetAddress().toString())).append(":").append(sc.socket().getPort()).toString().replace("/", "");
sc.configureBlocking(false);
sc.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
sc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
sc.setOption(StandardSocketOptions.TCP_NODELAY, true);
sc.register(selector, SelectionKey.OP_READ, address);
System.out.println("The server accepted at " + LocalDateTime.now() + " from " + address);
}
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
int read = sc.read(buffer);
if (read == -1) {
key.channel().close();
key.cancel();
} else {
Object object = convertByteToObject(buffer.array());
System.out.println("The server received at " + LocalDateTime.now() + " from " + key.attachment() + " for " + uptimeHttp.HttpRequestAddress);
buffer.clear();
}
}
}
}
}
publicstaticvoidmain(字符串args[])引发IOException{
选择器=选择器。打开();
ServerSocketChannel通道=ServerSocketChannel.open();
信道配置阻塞(假);
channel.socket().bind(新的InetSocketAddress(9001));
通道寄存器(选择器,选择键,操作接受);
System.out.println(“服务器在端口9001上的“+LocalDateTime.now()+”上侦听”);
迭代器;
选择键;
while(true){
selector.select();当您在紧循环中调用非阻塞操作时,CPU将以尽可能快的速度不断迭代,直到您停止它。这通常意味着您将100%的CPU用于执行循环
如果您看到的不到100%,则可能是您看到的是用户CPU,系统调用可能正在使用CPU的其余部分。当您在紧循环中调用非阻塞操作时,CPU将以尽可能快的速度不断迭代,直到您停止它。这通常意味着您将100%的CPU用于执行循环
如果您看到的不到100%,则可能是您看到的是用户CPU,系统调用可能正在使用CPU的其余部分。问题是,使用selectNow()
将导致一个紧循环,正如Peter建议的那样。也就是说,selectNow()
在特定情况下是一个有趣的选项。例如定时操作。您可以使用selectNow()
和一个高精度计时器来强制操作以特定频率进行。这是一个非常特殊的情况
因此,如果你想使用selectNow()
,你必须将它与Thread.sleep()
或其他类似的工具配对。问题是使用selectNow()
会像Peter建议的那样导致一个紧密的循环。也就是说,selectNow()
在特定情况下是一个有趣的选项。例如定时操作。您可以使用selectNow()
和一个高精度计时器来强制操作以特定频率进行。这是一个非常特殊的情况
因此,如果您想使用selectNow()
您必须将其与Thread.sleep()配对
或类似的东西。问题出在哪里?如果你忙着等待,你应该认为这会占用100%的CPU,或者你是说它不会占用100%的CPU?它几乎占到60-80%,但在我执行程序时没有连接。忙着等待应该占用100%的CPU,无论你是否有连接。如果你只得到60-80%,我会可能会想知道为什么它不高。也许其他20-40%在内核中,而你没有看到。如果你有一个繁忙的循环while(true){}
,无论是否有TCP连接,你都会期望它使用100%的CPU。我不明白你在问什么。你知道selectNow()
没有阻塞,那么为什么你对它没有阻塞感到惊讶?问题是什么?如果你忙着等待,你应该期望它使用100%的CPU,或者你是说它没有使用100%的CPU?它几乎60-80%,但在我执行程序时没有连接。忙着等待应该使用100%的CPU,无论你是否有连接不是。如果你只得到60-80%,我想知道为什么不更高。也许其他20-40%在内核中,而你没有看到。如果你有一个繁忙的循环while(true){}
无论是否存在TCP连接,您都希望它使用100%的CPU。我不明白您在问什么。您知道selectNow()
没有阻止,那么你为什么对它没有阻止感到惊讶呢?注意,但现在我是状态:你已达到问题限制抱歉,我们不再接受来自此帐户的问题。请参阅帮助中心了解更多信息。<----如何修复?@并且你可能必须开始选择答案或删除旧问题。注意,但现在我是状态:您已达到问题限制抱歉,我们不再接受来自此帐户的问题。有关详细信息,请参阅帮助中心。<----如何修复?@并且您可能必须开始选择答案或删除旧问题。