NIO 概述

前面说到 BIO 有着创建线程多,阻塞 CPU 等问题,因此为解决 BIO 的问题,NIO 作为同步非阻塞 IO模型,随 JDK1.4 而出生了。

在前面我们反复说过4个概念:同步、异步、阻塞、非阻塞。因此,我们就首先用最简单的语言说一下他们的区别,这里,我们心里暂时有个概念即可,在后面的学习过程中,还会对其进行深入的探讨学习。

概念对比

首先,我们先要确立一个概念,就是一个IO操作其实是分为两步的,

  1. 发起IO请求,即准备数据和区域;
  2. 实际的IO操作。

而区分一个 IO模型是同步还是异步,就取决于在进行第2个步骤时,即实际进行读写过程中,其是否会阻塞线程,如果会阻塞,那么就是同步的,如果不会(这里就需要操作系统内核来进行操作了),而是完成后,再通知操作线程,那么其就是异步的(AIO 就是 OS 来完成文件读写操作,在完成后通过消息机制来通过线程读写完毕)。

紧接着,区分一个模型是阻塞还是非阻塞,而是看其在数据没有准备完毕时,即连接建立后,但还没有数据过来,请求是需要卡在这等待,还是可以去干其他的事。

作为上文所述的 BIO 来说,首先因为数据是否读写完成,需要其一直在循环里判断,因此其是同步的,并且如果没有数据的话,其会一直卡在 read 操作上,不能继续往下执行,因此 BIO 是一种同步阻塞模型。

而 NIO 的数据读写完成与否,也需要自己来判断,因此也是同步的,但其只有当发生真正读写时,才会进行操作,如果没有准备完毕的话,则可以去做其他的事,因此 NIO 是一个同步非阻塞 IO模型。

总结一下,我们看一个模型是同步还是异步,其实看的是数据准备完毕后的消息通知机制;看是阻塞还是非阻塞的,则是看线程在请求后的线程状态。

下面就让我们来看一下 NIO 的基本概念。

NIO基本介绍

  1. 从 JDK1.4 后,官方引入的 IO 新特性,称为 NIO,是一个同步非阻塞模型;
  2. 相关类在 java.nio 包下,有 3大核心组件,Channel,Buffer,Selector
  3. NIO 是面向缓存区编程的,或者说可以是面向块的,而不是面向字节,因此极大提高了编程的灵活性;
  4. NIO 因为其核心组件和面向缓存区编程的特性,因此 数据总是从 Channel 读取到 Buffer 中,或者从Buffer 读取到 Channel 中,而 Selector 的作用就是监听多个 Channel,当 Channel 中有请求需要处理,就进行处理
  5. 。。。。。(官网或者搜一下,有很多,在这里就不多赘述了)

组件介绍

Buffer

缓存区本质是一个可以读写程序的内存块,我们可以将其简单理解为一个容器。在其内部还提供了一些方法,方便编程人员对其进行操作。

其所有可用子类如 ByteBuffer 等继承的父类为 Buffer,其有一些公有属性需要牢记。

属性 说明
mark 标记位,在调用 mark() 方法后,可以将当前 position 设为标记,后续在调用 reset() 方法时,就可以将 position 重置回该位置,如果不设置,则为负数,那么在调用 reset 时,会报错。(一般不需要设置)
position 缓存区内将要被写或读的节点下标,该值不能为负数,且永远小于等于 limit
limit 缓存区内第一个不能写或读的节点下标,该值不能为负数,且永远小于等于 capacity
capacity 缓存区被创建时指定的大小,该值不能为负数,且无法更改
mark <= position <= limit <= capacity

Buffer 代码演示

 IntBuffer intBuffer = IntBuffer.allocate(5);
for (int i = 1; i <= intBuffer.capacity(); i++) {
intBuffer.put(i);
}
// 翻转,读写切换
intBuffer.flip();
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
} intBuffer.position(0);
for (int i = 1; i <= intBuffer.capacity(); i++) {
intBuffer.put(i * i);
}
intBuffer.flip();
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
}
}

从上述代码中,可以看到 缓存区是一个可读可写的区域,且像数组容器一样可以在里面通过下标的方式进行移动,从而修改指定地方内容。

Channel

Channel 是流中的一个组件,在使用过程中,通过流来生成。

Channel 是 NIO 中的一个接口,其实现类中,我们使用的比较多的有FileChannel,ServerSocketChannel,SocketChannelDatagramChannel,其中 FileChannel 用于文件的读写,ServerSocketChannel 和 SocketChannel 用于TCP数据读写,DatagramChannel 用于 UDP 数据读写。

这里只描述一些 Channel 的一些简单概念,在后续文章:《文件操作》中,再用代码详细展示 Channel 的作用。

Selector

selector 解决的是 BIO 的线程阻塞和一个请求就需要创建一个线程的问题。selector 可以监控多个 Channel,如果对应的 Channel 有 Event 发生,就可以获取对应 Event,然后根据获取 Event 的不同去进行不同的处理逻辑,这样就不必每个请求都创建线程,并且只有当真正有读写事件发生时,才会进行操作。

也是只描述 Selector 的一些简单概念,在后续文章:《网络编程》中,再用代码详细展示 Selector 的作用。

总结

在本文中,我们初步介绍了 NIO 的概念,以及其的 3个核心组件:Buffer,Channel 和 Selector。

在后续的文章中,我们将对其分别进行介绍,通过 NIO 来逐步引入 Netty 的实现。

本文中代码已上传到 GitHub 上,地址为 https://github.com/wb1069003157/nettyPre-research ,欢迎大家来讨论,探讨。

文章在公众号「iceWang」第一手更新,有兴趣的朋友可以关注公众号,第一时间看到笔者分享的各项知识点,谢谢!笔芯!

Netty学习(2):IO模型之NIO初探的更多相关文章

  1. Netty学习之IO模型

    目录 1.1 同步.异步.阻塞.非阻塞     同步 VS 异步         同步         异步     阻塞 VS 非阻塞         阻塞         非阻塞     举例   ...

  2. Netty学习(4):NIO网络编程

    概述 在 Netty学习(3)中,我们已经学习了 Buffer 和 Channel 的概念, 接下来就让我们通过实现一个 NIO 的多人聊天服务器来深入理解 NIO 的第 3个组件:Selector. ...

  3. IO模型之NIO代码及其实践详解

    一.简介 NIO我们一般认为是New I/O(也是官方的叫法),因为它是相对于老的I/O类库新增的( JDK 1.4中的java.nio.*包中引入新的Java I/O库).但现在都称之为Non-bl ...

  4. 5月2日 python学习总结 IO模型

    IO模型 1.阻塞IO 2.非阻塞IO 3.多路复用IO 4.异步IO 一.阻塞IO blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了. 实际上,除非 ...

  5. Netty学习笔记(1)NIO三大组件

    1. Channel channel 有一点类似于 stream,它就是读写数据的双向通道,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前 ...

  6. 聊聊Netty那些事儿之从内核角度看IO模型

    从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...

  7. Netty 学习(一):服务端启动 & 客户端启动

    Netty 学习(一):服务端启动 & 客户端启动 作者: Grey 原文地址: 博客园:Netty 学习(一):服务端启动 & 客户端启动 CSDN:Netty 学习(一):服务端启 ...

  8. Netty 学习(二):服务端与客户端通信

    Netty 学习(二):服务端与客户端通信 作者: Grey 原文地址: 博客园:Netty 学习(二):服务端与客户端通信 CSDN:Netty 学习(二):服务端与客户端通信 说明 Netty 中 ...

  9. IO模型及高性能网络架构分析

    前言 操作系统一次IO调用过程 应用程序发起的一次IO操作包含两个阶段: IO调用:应用程序进程向操作系统内核发起调用. IO执行:操作系统内核完成IO操作. 操作系统内核完成IO操作还包括两个过程: ...

随机推荐

  1. Spring Boot2 系列教程(三十一)Spring Boot 构建 RESTful 风格应用

    RESTful ,到现在相信已经没人不知道这个东西了吧!关于 RESTful 的概念,我这里就不做过多介绍了,传统的 Struts 对 RESTful 支持不够友好 ,但是 SpringMVC 对于 ...

  2. GitHub 标星 2.4w+,最适合编程新手入门的宝藏项目推荐

      照惯例这周给大家推荐几个Github上高星的优秀项目,我的github:图灵的猫 ,也欢迎大家follow~ 下面这是第一个,也是首推的新手入门项目,以前我入门的时候如果有这样一个项目,知识广度和 ...

  3. Jquery图片上传功能整理

    最近在做一个图片上传到服务器的功能,之前基本没有什么JS的经验,用的也是网上的插件.做了一个星期才把他弄好,现在做一下总结,方便以后查看. 用的插件是WebUploader,上面有很多例子,我找的例子 ...

  4. OOP之重载

    PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的. 属性的重载通过调用类中的__set,__get,__isset,__unset方法来分别实现对不存在属性的赋值.读取.判断属性是否设 ...

  5. 致Java初学者

    致Java初学者 精心整理资料点击获取 前言 ​ 能看到这篇文章的朋友,应该都或多或少的了解Java,也许你现在是个菜鸟还在成长的路上.再此期间你一定遇到了很多困惑疑虑,对未来的学习方向感到很迷惑.作 ...

  6. vnpy源码阅读学习(2):学习PyQt5

    PyQt5的学习 花费了一个下午把PyQt5大概的学习了下.找了一个教程 PyQt5教程 跟着挨着把上面的案例做了一遍,大概知道PyQt5是如何生成窗体,以及控件的.基本上做到如果有需求要实现,查查手 ...

  7. .net core appsetting/获取配置文件

    修改appsetting 最近用Identity4所以需要做一个配置项项目 { "Logging": { "IncludeScopes": false, &qu ...

  8. Java中SMB的应用

    目录 SMB 服务操作 Ⅰ SMB简介 Ⅱ SMB配置 2.1 Windows SMB Ⅲ 添加SMB依赖 Ⅳ 路径格式 Ⅴ 操作共享 Ⅵ 登录验证 SMB 服务操作 Ⅰ SMB简介 ​ SMB(全称 ...

  9. ELK实战-elasticsearch安装

    操作系统: centos版本 7.4 防火墙 关闭 selinux 关闭 elasticsearch版本 6.3.2 java版本 1.8 server1 192.168.10.126 server2 ...

  10. 使用Airtest进行UI自动化测试

    一.环境搭建 1.Airtest客户端下载 访问官网http://airtest.netease.com/,根据自己的系统下载相应的客户端安装: 2.python工具下载与环境搭建 在本地python ...