NIO和IO到底有什么区别?有什么关系?

首先说一下核心区别:

NIO是以块的方式处理数据,但是IO是以最基础的字节流的形式去写入和读出的。所以在效率上的话,肯定是NIO效率比IO效率会高出很多。

NIO不在是和IO一样用OutputStream和InputStream 输入流的形式来进行处理数据的,但是又是基于这种流的形式,而是采用了通道和缓冲区的形式来进行处理数据的。

还有一点就是NIO的通道是可以双向的,但是IO中的流只能是单向的。

还有就是NIO的缓冲区(其实也就是一个字节数组)还可以进行分片,可以建立只读缓冲区、直接缓冲区和间接缓冲区,只读缓冲区很明显就是字面意思,直接缓冲区是为加快 I/O 速度,而以一种特殊的方式分配其内存的缓冲区。

先了解一下什么是通道,什么是缓冲区的概念

通道是个什么意思?

通道是对原 I/O 包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象(通道)。一个 Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。 Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。

正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

缓冲区是什么意思:

Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中

在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。

缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不 仅仅 是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程

缓冲区的类型:

ByteBuffer

CharBuffer

ShortBuffer

IntBuffer

LongBuffer

FloatBuffer

DoubleBuffer

NIO的底层工作原理

先来了解一下buffer的工作机制:

capacity 缓冲区数组的总长度

position 下一个要操作的数据元素的位置

limit 缓冲区数组中不可操作的下一个元素的位置,limit<=capacity

mark 用于记录当前 position 的前一个位置或者默认是 0

1.这一步其实是当我们刚开始初始化这个buffer数组的时候,开始默认是这样的

2、但是当你往buffer数组中开始写入的时候几个字节的时候就会变成下面的图,position会移动你数据的结束的下一个位置,这个时候你需要把buffer中的数据写到channel管道中,所以此时我们就需要用这个buffer.flip();方法,

3、当你调用完2中的方法时,这个时候就会变成下面的图了,这样的话其实就可以知道你刚刚写到buffer中的数据是在position—->limit之间,然后下一步调用clear();

4、这时底层操作系统就可以从缓冲区中正确读取这 5 个字节数据发送出去了。在下一次写数据之前我们在调一下 clear() 方法。缓冲区的索引状态又回到初始位置。(其实这一步有点像IO中的把转运字节数组 char[] buf = new char[1024]; 不足1024字节的部分给强制刷新出去的意思)

补充:

1、这里还要说明一下 mark,当我们调用 mark() 时,它将记录当前 position 的前一个位置,当我们调用 reset 时,position 将恢复 mark 记录下来的值

2. clear()方法会:清空整个缓冲区。position将被设回0,limit被设置成 capacity的值(这个个人的理解就是当你在flip()方法的基础上已经记住你写入了多少字节数据,直接把position到limit之间的也就是你写入已经记住的数据给“复制”到管道中)

3 . 当你把缓冲区的数局写入到管道中的时候,你需要调用flip()方法将Buffer从写模式切换到读模式,调用flip()方法会将position设回0,并将limit设置成之前position的值。buf.flip();(其实我个人理解的就相当于先记住缓冲区缓冲了多少数据)

NIO其实就是主要利用缓冲区来进行传输字节:

(客户端和服务端又是怎么进行通信和传输的,以后再来更新)

NIO 工作代码示例

public void selector() throws IOException {

//先给缓冲区申请内存空间

ByteBuffer buffer = ByteBuffer.allocate(1024);

//打开Selector为了它可以轮询每个 Channel 的状态

Selector selector = Selector.open();

ServerSocketChannel ssc = ServerSocketChannel.open();

ssc.configureBlocking(false);//设置为非阻塞方式

ssc.socket().bind(new InetSocketAddress(8080));

ssc.register(selector, SelectionKey.OP_ACCEPT);//注册监听的事件

while (true) {

Set selectedKeys = selector.selectedKeys();//取得所有key集合

Iterator it = selectedKeys.iterator();

while (it.hasNext()) {

SelectionKey key = (SelectionKey) it.next();

if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {

ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();

SocketChannel sc = ssChannel.accept();//接受到服务端的请求

sc.configureBlocking(false);

sc.register(selector, SelectionKey.OP_READ);

it.remove();

} else if

((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {

SocketChannel sc = (SocketChannel) key.channel();

while (true) {

buffer.clear();

int n = sc.read(buffer);//读取数据

if (n <= 0) {

break;

}

buffer.flip();

}

it.remove();

}

}

}

}

最后给大家看一下整体的NIO的示意图

转载于:https://www.cnblogs.com/fanblogs/p/11039269.html

【转】NIO的定义和原理是什么?相关推荐

  1. IO、NIO、AIO 内部原理分析

    相关文章 NIO 之 Selector实现原理 NIO 之 Channel实现原理 NIO 之 ByteBuffer实现原理 阻塞IO 所有的读写IO都是阻塞操作. 多路复用模型 select/pol ...

  2. NIO 之 Selector实现原理

    相关文章 NIO 之 ByteBuffer实现原理 NIO 之 Channel实现原理 NIO 之 Selector实现原理 概述 Selector允许单线程处理多个 Channel.如果你的应用打开 ...

  3. NIO 之 Channel实现原理

    相关文章 IO.NIO.AIO 内部原理分析 NIO 之 Selector实现原理 NIO 之 ByteBuffer实现原理 NIO概述 Java NIO 由以下几个核心部分组成: Channels ...

  4. NIO 之 ByteBuffer实现原理

    相关文章 IO.NIO.AIO 内部原理分析 NIO 之 Selector实现原理 NIO 之 Channel实现原理 前言 Java NIO 主要由下面3部分组成: Buffer Channel S ...

  5. 深入浅出NIO之Selector实现原理

    2019独角兽企业重金招聘Python工程师标准>>> 前言 Java NIO 由以下几个核心部分组成: 1.Buffer 2.Channel 3.Selector Buffer和C ...

  6. 赫夫曼树的定义及原理

    参考<大话数据结构>        以学生成绩为例进行分析,正常的学生成绩的分布范围如下: 下面的图是普通的学生成绩判断,粗略的看什么问题,可是通常都认为,一张好的考卷应该是让学生的成绩大 ...

  7. python函数定义及调用-python函数声明和调用定义及原理详解

    这篇文章主要介绍了python函数声明和调用定义及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 函数是指代码片段,可以重复调用,比如我们前 ...

  8. 微点“主动防御”的科学定义与原理是什么?

    发贴真难啊,新版csdn超慢!刚试用了一下,初看微点界面很专业,没有计算机基础人用起来可能要费些事.其实很早以前就听说过了,当时以为是概念炒作,使我想起了DOS时代的"行天98", ...

  9. 语言的定义——编译原理

    语言的定义--编译原理 给定文法G=(VT,VN,P,S),如果α→β∈P,那么可以将符号串中的γαδ中的α替换为β,记作 γαδ⇒γβδ,此时称γαδ直接推导出γβδ. 推导(derivation) ...

最新文章

  1. 添加引用方式抛出和捕获干净的WebService异常
  2. 此字符不允许在标识符中使用_计算机中C语言的-基本语法
  3. 软件测试理论之测试用例设计六把刀
  4. 为什么现在的人越来越不幸福
  5. bilibili深入理解计算机系统笔记(1):汇编模拟器能跑了
  6. Lesson 8.1Lesson 8.2 决策树的核心思想与建模流程CART分类树的建模流程与sklearn评估器参数详解
  7. dts数据库迁移工具_传统数据库迁移上云利器-ADAM
  8. kotlin半生对象_Kotlin程序| 随播对象特征
  9. 开源社区团购微商城小程序,直播
  10. tcp假连接_ESTABLISHED状态的连接收到 SYN 会回复什么?
  11. 高斯滤波/高斯平滑/高斯模糊的实现及其快速算法(Gaussian Filter, Gaussian Smooth, Gaussian Blur, Fast implementation)
  12. 实现option上下移动_jQuery操作Select的Option上下移动及移除添加等等
  13. Win10内置应用误卸载恢复方法
  14. 计算机启动黑屏时间很长,电脑开机黑屏时间长怎么办?[多图]
  15. 概率熵物质混乱能量耗散信息熵
  16. jacob实现ppt转图片时存在的问题
  17. 什么是在制品限制?通过这篇文章,让你搞明白
  18. sqlserver 电话号3-8位用*号代替
  19. ASTERISK+LINUX+PHP 的WebCall, 网页回拨源码
  20. halcon循环语句,条件句结构格式

热门文章

  1. html桌面卡牌效果,html+css实现响应式卡片悬停效果
  2. ajax从mysql提取数据在html中_Python骚操作,提取pdf文件中的表格数据!
  3. android 数据存储怎么保存图片_遇到验证码怎么办?Python编写一个验证码图片数据标注GUI程序!...
  4. php使用file,PHP中is_file()函数使用指南
  5. nginx php unix负载,使用nginx配置多个php fastcgi负载均衡
  6. ad域帐号登录提示无法处理请求_面试官:说一下单点登录的几种实现方式
  7. linux课程教学设计,《LINUX操作系统》课程整体教学设计.doc
  8. 思科路由器交换机模拟软件_eNSP模拟器上学习华为三层交换机与路由器对接
  9. python 自动补全函数括号_Python学习笔记(二)
  10. python 使用socks 爬虫_小白学 Python 爬虫(17):Requests 基础使用