美文网首页
Java AIO NIO的IO类型的个人理解

Java AIO NIO的IO类型的个人理解

作者: 烟雨_任平生 | 来源:发表于2017-05-12 23:16 被阅读0次

最近刚刚接触AIO和NIO,对两者的IO类型(同步、异步、阻塞、非阻塞)一直很困惑,下面是自己的理解,希望各位大神能够指点一二。

Java NIO的Selector属于多路复用IO,select()方法本身是阻塞线程的,其要不停轮询其上注册的Channel,查看是否有IO就绪的Channel。之所以说其属于同步非阻塞IO的原因是,Selector并不是阻塞于等待IO就绪,所以属于非阻塞IO;其需要不停轮询Channel,并且IO就绪后需要应用程序主动从操作系统内核中读取数据,所以属于同步IO。参考代码如下:

private class ClientThread extends Thread {
 @Override
 public void run() {
     try {
         while (selector.select() > 0) {
             for (SelectionKey sk : selector.selectedKeys()) {
                 selector.selectedKeys().remove(sk);
                 if (sk.isReadable()) {
                     SocketChannel sc = (SocketChannel) sk.channel();
                     ByteBuffer buffer = ByteBuffer.allocate(1024);
                     String content = "";
                     while (sc.read(buffer) > 0) {
                         sc.read(buffer);
                         buffer.flip();
                         content += charset.decode(buffer);
                     }
                     System.out.println("聊天信息: " + content);
                     sk.interestOps(SelectionKey.OP_READ);
                 }
             }
         }
     } catch (IOException e) {
         e.printStackTrace();
     }
 }
}

AIO需要注册CompletionHandler事件处理器,CompletionHandler不关注IO就绪事件,而是关注IO完成事件,数据完全由操作系统内核读取到缓冲区,应用程序不需要进行实际的读写操作,所以说其属于异步IO。

sc.read(buffer, null, new CompletionHandler<Integer, Object>() {
    @Override
    public void completed(Integer result, Object attachment) {
        buffer.flip();
        String content = StandardCharsets.UTF_8.decode(buffer).toString();
        //遍历每个Channel, 将收到的信息写入各Channel中
        for (AsynchronousSocketChannel c : AIOServer.channelList) {
            try {
                c.write(ByteBuffer.wrap(content.getBytes("UTF-8"))).get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        buffer.clear();
        //读取下一次数据
        sc.read(buffer, null, this);
    }

   @Override
    public void failed(Throwable exc, Object attachment) {
        System.out.println("读取数据失败:" + exc);
        //从该Channel中读取数据失败,将该Channel删除
        AIOServer.channelList.remove(sc);
    }
});

相关文章

网友评论

      本文标题:Java AIO NIO的IO类型的个人理解

      本文链接:https://www.haomeiwen.com/subject/sfitxxtx.html