我正在研究java.nio,它提到nio是非阻塞io,如下例所示。
int noOfKeys = selector.select();
System.out.println("Number of selected keys: " + noOfKeys);
Set selectedKeys = selector.selectedKeys();
Iterator iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey ky = iter.next();
if (ky.isAcceptable()) {
// Accept the new client connection
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
// Add the new connection to the selector
client.register(selector, SelectionKey.OP_READ);
System.out.println("Accepted new connection from client: " + client);
}
else if (ky.isReadable()) {
// Read the data from client
无处不在我看到一个循环,它检查可读密钥和可写密钥条件并继续非阻塞写/读。是否可以在循环中同时处理两个写入/读取作为单个选择器?任何帮助或指针都非常有用。另外对于套接字连接,它应该接受连接,然后它应该执行写或读。为什么它不阻挡io?这是顺序吗?
答案 0 :(得分:3)
非阻塞I / O不是同一个并行I / O.非阻塞I / O允许的是I / O而不阻塞调用线程。通常,线程会等待系统调用完成,这会阻止调用线程执行任何其他工作。对于非阻塞I / O,如果操作会阻塞,则延迟允许调用线程执行其他工作(例如,其他读/写/接受)。
您可以使用实际的单独线程进行I / O并同时执行多个I / O操作,但通常有多个客户端执行I / O而不是CPU。随着每个I / O集的线程数增加到CPU数以上,它们开始在CPU上争用时间,操作系统必须安排该CPU。因此,每个I / O操作开始暗示上下文切换,这是昂贵的。这种额外的成本以及其他各种成本是并行I / O通常不能很好地运行或扩展的原因。
但是,非阻塞I / O在概念上可以被认为是异步或并行的,因为通常会阻塞的操作不会,并且允许另一个I / O操作运行。所以,实际操作重叠。但是,由于它们在同一个线程中运行,因此避免了上下文切换成本和并行I / O的其他各种成本。
实际上它是顺序的,并且在响应I / O时执行应用程序代码所花费的时间确实增加了延迟。通常,该时间量小于上下文切换,这意味着非阻塞I / O通常执行并且比并行I / O更好地扩展。
使用Java非阻塞I / O,您可以使用选择器进行多路复用。因此,selector.select()
检索所有准备好进行I / O而没有阻塞的客户端。这就是您使用选择器注册客户端频道的原因。您告诉选择器您想知道它什么时候准备好进行I / O而不会阻塞。
另外,只是注释,但 NIO 仅代表新I / O 。非阻塞I / O只是一个子集。
维基百科的描述并不好,但它们可能有所帮助......