我正在开发一个基于NIO的非阻塞SocketChannels的通信库,因此我可以使用select
来保持我的线程低CPU使用率(并加快对其他事件的反应时间)。
SocketChannel
是在我的线程外部创建的,并添加到它处理的列表中,将它们标记为非阻塞,并将它们添加到Selector
以进行READ操作(并在需要时写入,但这不会发生在我的问题)。
我有一个小的Swing应用程序用于本地运行的测试,可以是客户端或服务器:客户端连接到服务器一个,他们可以互相发送消息。一旦在客户端和服务器之间建立连接,就会非常简单并且工作正常,除了CPU的最高100%(每个jvm 50%)。
正在运行jvisualvm
向我显示sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run()
占用了98%的申请时间,仅计算3次方法调用!
强制堆栈跟踪显示read
上的FilteredInputStream
上的Socket
操作阻塞了ConnectionHandler.run()
。
我有点困惑,因为我不使用RMI(虽然我可以理解NIO和RMI可以共享“传输”代码部分)。我已经看到了一些类似的问题,但每个都是专门使用RMI,我不是。我看到的答案是这个SocketChannel
方法负责编组/解组事件,在这里我得到100%的CPU没有任何网络流量。我只能在套接字上推断出一个活跃的等待,但这听起来很奇怪,特别是对于非阻塞{{1}} ......
任何想法都将不胜感激!
答案 0 :(得分:2)
我跟踪CPU使用率降至select(int timeout)
,无论timeout
值如何,都会立即返回0。我对这个函数的理解是它会阻塞,直到弹出一个选定的操作,或达到超时(如Javadoc中所述)。
但是,如果发现问题this other StackOverflow post有同样的问题:接受连接后,OP_CONNECT
操作必须取消。
非常感谢@Alexander和@EJP澄清OP_WRITE
/ OP_CONNECT
相似之处。