在单个nio选择器中并行写入/读取

时间:2015-08-03 14:24:52

标签: java io nio

我正在研究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?这是顺序吗?

1 个答案:

答案 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只是一个子集。

维基百科的描述并不好,但它们可能有所帮助......